SQLServer2005でクエリを調整しています。実際の質問は最後にあることに注意してください。次のクエリがあります。ptoとphの両方に約3000万行あります。クエリは最初は非常に遅く実行されます(3分)。そこで、pto、phにそれぞれ2つのインデックスを追加しました。
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ミリ秒で実行されます。素晴らしい。実行プランも非常に単純で、2つのテーブルから作成されたインデックスを使用し、recipient_id列でハッシュ結合を実行してからStream Aggregateを実行してMAX(ph.txn_date_time)を実行します。したがって、クエリのすべての列は、追加された2つのインデックスでカバーされます。
問題は、recipient_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列にマージ結合が表示されます。クエリも170ミリ秒で実行されます。これで、オプティマイザは明らかに、両方のインデックスのRECEIPT_IDがソートされていると考えているため、マージ結合が使用されます。しかし、最初のケースでなぜそう思わないのかわかりませんか?