实体框架索引所有外键列

8 sql sql-server entity-framework

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

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

我读了这个问题:实体框架代码第一外键添加索引,每个人似乎都说这是一个伟大,有效的想法,但我不知道如何; 索引列非常特定于环境.例如,EF在我的表上索引FK,几乎从不(~1%)用于搜索,也在源表上,这意味着即使我加入其他表,我也在使用它的PK搜索FK的链表......在那种情况下(我知道)将FK编入索引没有任何好处.

我的问题:

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

我的计划是删除一些可疑的索引,但我想确认没有一些我缺少的优化概念.

Stu*_*tLC 7

在EF Code First中,您建模外键关系的一般原因是实体之间的可导航性.考虑一个简单的场景,CountryCity为以下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在子表中使用外键(即,按国家/地区聚类城市).这通常在父:子表关系中是有益的,其中通常同时检索父对象的所有子行.

  • @Kalmino - 如果你从未做过反向导航,那为什么要建模呢? (7认同)
  • OP声称索引与他/她的查询无关。这主要只是重申了什么。 (2认同)
  • @Kalmino - 我没有问你为什么要塑造人物 - >地址关系,我问你为什么要建模地址 - >人物关系.即,为什么你有反向导航财产? (2认同)