如果我在 2 个不同的列中搜索 id,是否需要在 EF Core 中为 id 建立索引?

Do I need to index on a id in EF Core if I'm searching for an id in 2 different columns?

如果我执行如下查询,我将在两个不同的列中搜索相同的 ID。我应该有这样的索引吗?或者我应该创建 2 个单独的索引,每个列一个?

modelBuilder.Entity<Transfer>()
  .HasIndex(p => new { p.SenderId, p.ReceiverId });

查询:

var transfersCount = await _dbContext.Transfers
    .Where(p => p.ReceiverId == user.Id || p.SenderId == user.Id)
.CountAsync();

如果我有下面这样的查询,我是否需要在所有 4 列上使用多列索引?

var transfersCount = await _dbContext.Transfers
.Where(p => (p.SenderId == user.Id || p.ReceiverId == user.Id) &&
      (!transferParams.Status.HasValue || p.TransferStatus == (TransferStatus)transferParams.Status) &&
      (!transferParams.Type.HasValue || p.TransferType == (TransferType)transferParams.Type))
.CountAsync();

我推荐两个 single-column 指数。

两个 single-column 索引将在此查询中执行得更好,因为两个列都在完全有序的索引中。相比之下,在 multi-column 索引中,只有第一列在索引中完全排序。

如果您对发送方和接收方使用 AND 条件,那么您将受益于 multi-column 索引。 multi-column 索引非常适用于多个列具有条件语句的情况,这些条件语句必须全部被评估以构建结果集(例如, WHERE receiver = 1 AND sender = 2)。在 OR 条件下,multi-column 索引将被用作仅针对第一列的 single-column 索引;第二列将没有索引。

索引设计的全部复杂性需要的不仅仅是一个 SO 答案来解释;可能有关于它的书籍,并且它将作为数据库管理员工作的合理比例

索引需要维护成本,因此您通常会努力拥有尽可能少的索引,以便为您提供最大的灵活性来完成您想要做的事情。通常,索引会有一些定义其键的列和对 table 中具有这些键的行的引用。使用索引时,数据库引擎可以快速查找键,并发现需要从中读取哪些行。然后它将查找这些行作为辅助操作。 索引还可以存储不属于查找键的 table 数据,因此您可能会发现自己创建的索引还跟踪行中的其他列,以便在数据库找到它要查找的键时索引它还可以访问查询所需的行数据,并且不需要启动第二个查找操作来查找该行。如果查询需要 table 中的太多行,数据库可能会决定完全跳过使用索引;有一些阈值,超过该阈值直接从 table 读取所有行并搜索它们而不是使用索引查找需要读取哪些行的间接访问

会更快

一个索引索引的列可以服务于多个查询;顺序很重要。如果你总是按名字查询一个人,有时也按年龄查询,但你从不单独按年龄查询,那么索引 (name,age) 比 (age,name) 更好。 (name,age) 上的索引可以为 WHERE name = ...WHERR name = ... and age = ... 提供查询服务。如果您在 where 子句中使用 OR 关键字,您可以将其视为完全需要其自己的索引的单独查询。实际上,数据库可能决定将 运行“姓名或年龄”作为两个并行查询,并合并结果以删除重复项。如果您的应用程序需要稍后更改,而不是仅仅查询 (name), (name and age) 的混合,它现在经常查询 (name), (name and age), (name or age), (age), ( age and height) 那么有两个索引可能是有意义的:(name, age) 加上 (age, height)。数据库可以使用其中的一部分或全部来为常见查询提供服务。请记住,使用索引的一部分只能从左到右使用。 (name, age) 上的索引通常不会单独提供年龄查询。

如果您正在使用 SQLServer 和 SSMS,您可能会发现显示查询计划还会显示缺少的索引建议,值得仔细考虑是否需要添加索引。部署到 Microsoft azure 的应用程序还会自动查看由于缺少索引而导致性能下降的常见查询,这可能是查看 运行 查询并了解如何扩展现有或新索引的动力或重新排列以覆盖它;正如最初指出的那样,几行的单一 SO 答案并不是真正的东西可以让你为“总是这样做,它会很好”做好准备 - 大规模运营的公司雇用的人的唯一任务是确保数据库 运行s 好吧,他们通常对开发者抱怨很多,对 entity framework 之类的事情更是如此,因为 EF LINQ 查询是一个与实际 SQL 断开连接的层 运行 并且可能不会是获取数据的最佳方法。所有这些你都必须面对。

在这种特殊情况下,SenderId+TransferStatus+TransferType 上的索引和 ReceiverId+TransferStatus+TransferType 上的另一个索引似乎可以帮助显示的两个查询,但我不会说“肯定会那样做”在不全面了解此 table 包含的所有内容的情况下,这些列中有多少不同的值以及它们在应用程序上下文中的用途。如果 Sender/Receiver 是唯一的,那么将更多列作为键添加到索引中可能没有意义。如果 TransferStatus 和 Type 发生变化,使得它们的某些组合有助于从数百行中唯一地识别某些特定行,那么它可能有意义,但是如果此查询每天仅 运行s 一次,而另一个查询则每天使用 10 次第二...变量和未知数太多,无法为所提出的问题提供具体答案;不要过早地优化 - 索引列只是因为它们在某个地方的某些 where 子句中使用会过早