我正在调整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列上执行Hash连接,然后使用Stream Aggregate执行MAX(ph.txn_date_time)。因此查询中的每一列都由两个添加的索引覆盖。
问题是为什么它在receipt_id列上使用了哈希联接?我的意思是,因为两个索引中的RECEIPT_ID都已排序,优化器应该使用合并连接。找出为什么我将第一个索引更改为以下(在Units_No之前放置RECEIPT_ID)。
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都已排序,因此使用了合并连接。但我不明白为什么在第一种情况下它不这么认为呢?
答案 0 :(得分:3)
原因是RECEIPT_ID
不是您拥有的索引中的第一个排序项。你的路上有units_no
。
想象一下,你有一排由出版商订购的书籍,然后是作者,然后是颜色。如果您想查找特定颜色的所有书籍,您需要访问每个出版商部分,然后访问每个作者部分,然后找到正确颜色的书籍。所以“索引”不太适合按颜色扫描,即使你可以一直说这些书是按颜色分类的。
当您添加最后一个索引时,RECEIPT_ID
可用排序,因为您要按SUBTYPE
限制查询。因此,双方的所有RECEIPT_ID
值都是可用的,成本很低,并且选择了合并连接。