实体框架索引所有外键列

时间:2015-04-17 18:58:17

标签: sql sql-server entity-framework

这可能是一个基于意见的问题太过分了,但这里有:

我发现了一个有趣的实体框架和数据库迁移的怪癖。看来每当我们创建一个外键时,它也会在该列上创建一个索引。

我读到了这个问题:Entity Framework Code First Foreign Key adding Index as well,每个人似乎都说这是一个伟大而有效的想法,但我不知道如何;索引列非常特定于环境。例如,EF在我的桌子上索引FK几乎从不(约1%)用于搜索,也在源表上,这意味着即使我加入其他表格,我也在搜索FK'使用它的PK链接表...在那种情况下(我意识到)将FK编入索引没有任何好处。

我的问题:

我错过了什么吗?是否有某些原因我想要索引一个从未搜索过的FK列,并且总是在任何连接的源表中?

我的计划是删除其中一些有问题的索引,但我想确认一下我没有找到一些优化概念。

2 个答案:

答案 0 :(得分:7)

在EF Code First中,您建模外键关系的一般原因是实体之间的可导航性。考虑CountryCity的简单场景,并为以下LINQ语句定义了急切加载:

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将需要扫描Cities表,以便在JOIN期间过滤Country的城市。

<强> TL; DR

外键are recommended上的索引,即使您不直接过滤外键,联接中仍然需要它。对此的例外似乎是非常人为的:

  • 如果外键的选择性非常低,例如在上述情况下,如果国家表中50%的所有城市都在日本,那么该指数就无用了。

  • 如果您实际上没有浏览过这段关系。

另一个优化考虑因素是是否在子表的Clustered Index中使用外键(即按国家/地区划分群集城市)。这在父:子表关系中通常是有益的,其中通常同时检索父项的所有子行。

答案 1 :(得分:1)

简短回答。否。

为了略微扩展,在数据库创建时,实体框架不知道每个表或实体将有多少记录,也不知道如何查询实体。

*在我看来*外键的创建更可能是错误的,我使用不同的ORM进行了大量的性能问题,这需要更长的时间来诊断,因为我认为我在文档中已经阅读了它表现得很好同样的方式。

如果要仔细检查,可以检查EF生成的Sql语句并手动运行它。

您比EF更了解您的数据,如果您手动删除索引,它应该可以正常工作。

IIRC如果使用正确的命名约定,你可以创建单向导航属性,虽然这是前一段时间,我从未检查过是否创建了索引。