【问题标题】:a query using covering index, merge join, hash join使用覆盖索引、合并连接、哈希连接的查询
【发布时间】:2012-08-19 02:12:29
【问题描述】:

我正在调整 SQL Server 2005 上的查询。 请注意,真正的问题在最后。 我有以下查询,pto 和 ph 都有大约 3000 万行。查询最初运行速度很慢(3 分钟)。所以我分别在 pto 和 ph 上添加了两个索引。

        SELECT 
            MAX(ph.txn_date_time)
        FROM 
            pto AS pto WITH (NOLOCK) 
            INNER JOIN ph AS ph WITH (NOLOCK) ON ph.receipt_id = pto.receipt_id
        WHERE 
                pto.subtype = 'ff'
            AND pto.Units_No > 0
            AND ph.branch_id = 5



CREATE NONCLUSTERED INDEX [IX_pto_subTypeUnitReceipt] ON [dbo].[pto] 
(
    [SUBTYPE] ASC,
    [Units_No] ASC,
    [RECEIPT_ID] ASC

)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = ON, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Indexes]


CREATE NONCLUSTERED INDEX [IX_ph_branchReceiptTxn] ON [dbo].[ph] 
(
    [BRANCH_ID] ASC,
    [RECEIPT_ID] ASC,
    [TXN_DATE_TIME] ASC
)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Indexes]

现在查询在 350 毫秒内运行。伟大的。执行计划也很简单,它使用从两个表中创建的索引并在receipt_id 列上进行哈希连接,然后使用Stream Aggregate 进行MAX(ph.txn_date_time)。所以查询中的每一列都被两个添加的索引覆盖。

问题是为什么它在receipt_id 列上使用哈希连接?我的意思是,由于两个索引中的 RECEIPT_ID 都已排序,因此优化器应该使用合并连接。为了弄清楚为什么我将第一个索引更改为下面(将 RECEIPT_ID 放在 Units_No 之前)。

CREATE NONCLUSTERED INDEX [IX_pto_subTypeUnitReceipt] ON [dbo].[pto] 
(
[SUBTYPE] ASC,
[RECEIPT_ID] ASC,
[Units_No] ASC


)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = ON, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Indexes]

现在我在 RECEIPT_ID 列上看到了 Merge 连接。查询也在 170 毫秒内运行。现在显然优化器认为两个索引中的 RECEIPT_ID 都已排序,因此使用了合并连接。但我不明白为什么在第一种情况下它不这么认为?

【问题讨论】:

    标签: sql-server tsql sql-server-2005 join sql-execution-plan


    【解决方案1】:

    原因是RECEIPT_ID 不是您拥有的索引中的第一个排序项。你有units_no在路上。

    想象一下,您有一排书按出版商订购,然后按作者订购,然后按颜色订购。如果您想查找特定颜色的所有书籍,您需要访问每个出版商部分,然后是每个作者部分,然后找到正确颜色的书籍。因此,“索引”不太适合按颜色扫描,即使您可以说书籍是按颜色排序的。

    当您添加最后一个索引时,RECEIPT_ID 可以排序,因为您将查询限制为SUBTYPE。因此,双方的所有RECEIPT_ID 值都可以轻松获得,成本低并且选择了合并连接。

    【讨论】:

    • 我明白了。如果receipt_id 不是排序列中的第一列,则不能保证被排序。在这种情况下,子类型是固定的,因此receipt_id 保证在它是第二列时是有序的。谢谢。
    猜你喜欢
    • 2012-09-16
    • 2018-06-17
    • 2021-12-20
    • 2017-07-13
    • 2016-05-20
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多