【问题标题】:Howto set correct Index for SQL join with where clause如何使用 where 子句为 SQL 连接设置正确的索引
【发布时间】:2019-04-04 08:39:41
【问题描述】:

我已经在谷歌搜索了一段时间,但我没有找到解决我的“问题”的答案。

我有 3 个具有以下结构的示例表。

客户:

  • 客户 ID
  • 名字
  • 姓氏
  • 性别
  • 已删除

发票:

  • 发票编号
  • 客户 ID
  • 金额
  • 职位
  • 有效

发票位置:

  • InvoicePosId
  • 发票编号
  • 职位名称
  • 已付费

现在我想通过以下查询加入他们。

SELECT T1.FirstName,
       T1.LastName,
       T2.Amount,
       T3.PosName
FROM Customer AS T1
     JOIN Invoice AS T2 ON T1.CustomerId = T2.CustomerId
     JOIN InvoicePos AS T3 ON T2.InvoiceId = T3.InvoiceId
WHERE T1.FirstName = 'A'
  AND T1.LastName = 'B'
  AND T2.Positions = 3
  AND T3.IsPaid = 1;

对于表 Customer,我有一个 FirstName、LastName、CustomerId 的索引

对于InvoicePos,我有一个 IsPaid、InvoiceId、InvoicePosId 的索引

但是我应该为 Table Invoice 使用什么索引?

【问题讨论】:

  • 索引不是可以简单地用简单的答案“教”的东西;需要更深入的了解,您可能会更好地阅读文章和文档,甚至参加课程,了解索引表的最佳方法。你没有提到主键,如果它们是集群的,这也有很大的不同。
  • t1、t2 和 t3 是糟糕的表别名。使用有意义的表别名,例如 C 代表客户。

标签: sql sql-server join indexing where-clause


【解决方案1】:

对于这个查询:

SELECT T1.FirstName, T1.LastName, T2.Amount, T3.PosName
FROM Customer T1 JOIN
     Invoice T2
     ON T1.CustomerId = T2.CustomerId JOIN
     InvoicePos T3
     ON T2.InvoiceId = T3.InvoiceId
WHERE T1.FirstName = 'A' AND
      T1.LastName = 'B' AND
      T2.Positions = 3 AND
      T3.IsPaid = 1;

我会推荐以下索引:

  • Customer(FirstName, LastName, CustomerId)
  • Invoice(CustomerId, InvoiceId, Positions, Amount)
  • InvoicePost(InvoiceId, IsPaid, PosName)

首先,这些是您查询的覆盖索引。因此,只需要索引。如果您在 SELECT 中有其他列,则可以从索引中删除 SELECT-only 列。

这个想法是从最有选择性的WHERE 条件开始。我猜名称限制是最严格的。因此,索引从Customer 开始并使用WHERE 条件。然后,添加来自 ONSELECT 子句的其他列。

对于其余表,JOIN 列是索引中的第一个键,然后是 WHERESELECT 列。

【讨论】:

  • 感谢这有助于我更好地理解问题。剩下的唯一问题是表 2 如何设置索引。 “CustomerId + Positions”或“InvoiceId + Positions”
【解决方案2】:

您还可以对您的查询运行查询优化器,SQL 将为您提供最佳索引来应用,并显示性能提升百分比。

【讨论】:

  • 如果它是非聚集索引,那将无济于事;它不会是一个覆盖索引。即使这样,单独在这 2 列上的聚集索引也不会帮助WHERE,它不会引用这些列。
【解决方案3】:

对于这个精确的查询,在 Table2/Invoice 上加上CustomerId, Positions 的索引是理想的。

虽然通常以下索引是有意义的:

Customer:
  unique index on CustomerId
  index on LastName, FirstName
Invoice:
  unique index on InvoiceId
  index on CustomerId
InvoicePos:
  unique index on InvoicePosId
  unique index on InvoiceId, InvoiceId
  index on IsPaid, InvoiceId  (for your scenario)

【讨论】:

    【解决方案4】:

    使用这些索引:

    Create Index IX__Customer_001 on Customer (CustomerId,FirstName,LastName)
    Create Index IX__Invoice_001 on Invoice (CustomerId,InvoiceId,Positions) include (Amount)
    Create Index IX__InvoicePos_001 on InvoicePos (InvoiceId,IsPaid) include (PosName)
    

    您必须使用仅用作包含子句上的选择列的字段,并将谓词放在关键列上

    【讨论】:

    • 欢迎来到 Stack Overflow!如果您花时间解释您的答案会有所帮助,因此 OP 会理解您做出这些选择的原因。仅代码回答通常无助于其他用户的学习,尤其是在他们不理解的情况下。
    【解决方案5】:

    我的主要问题是了解查询的解决顺序。

    AI 列上有一些索引(CostumerId、InvoiceId、InvoicePosId)。

    表 1 上的索引(Firstname、Lastname、CostumerId)是有意义的,因为它过滤了名称,然后与 Invoicetable 连接。

    但第二个索引对我来说并不清楚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-03
      • 2013-04-13
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 2011-01-01
      相关资源
      最近更新 更多