8 sql sql-server entity-framework
这可能是一个基于意见的问题,但这里有:
我发现了一个有趣的实体框架和数据库迁移的怪癖.看来每当我们创建一个外键时,它也会在该列上创建一个索引.
我读了这个问题:实体框架代码第一外键添加索引,每个人似乎都说这是一个伟大,有效的想法,但我不知道如何; 索引列非常特定于环境.例如,EF在我的表上索引FK,几乎从不(~1%)用于搜索,也在源表上,这意味着即使我加入其他表,我也在使用它的PK搜索FK的链表......在那种情况下(我知道)将FK编入索引没有任何好处.
我的问题:
我错过了什么吗?是否有某些原因我想要索引一个从未搜索过的FK列,并且总是在任何连接的源表中?
我的计划是删除一些可疑的索引,但我想确认没有一些我缺少的优化概念.
在EF Code First中,您建模外键关系的一般原因是实体之间的可导航性.考虑一个简单的场景,Country
并City
为以下LINQ语句定义了急切加载:
var someQuery =
db.Countries
.Include(co => co.City)
.Where(co => co.Name == "Japan")
.Select(...);
Run Code Online (Sandbox Code Playgroud)
这将导致查询:
SELECT *
FROM Country co
INNER JOIN City ci
ON ci.CountryId = co.ID
WHERE co.Name = 'Japan';
Run Code Online (Sandbox Code Playgroud)
如果没有外键索引City.CountryId
,SQL将需要扫描Cities表,以便在JOIN期间过滤Country的城市.
TL; DR
建议使用外键索引,即使您不直接在外键上过滤,在联接中仍然需要它.这种情况的例外似乎是非常人为的:
如果外键的选择性非常低,例如在上述场景中,如果国家表中50%的所有城市都在日本,则索引将没有用处.
如果你实际上没有浏览过这段关系.
另一个优化考虑因素是是否Clustered Index
在子表中使用外键(即,按国家/地区聚类城市).这通常在父:子表关系中是有益的,其中通常同时检索父对象的所有子行.