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