3

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がソートされていると考えているため、マージ結合が使用されます。しかし、最初のケースでなぜそう思わないのかわかりませんか?

4

1 に答える 1

3

その理由は、RECEIPT_IDあなたが持っていたインデックスの最初にソートされたアイテムではないからです。あなたはunits_no邪魔をしました。

出版社、著者、色の順に並べられた本の列があると想像してみてください。特定の色の本をすべて見つけたい場合は、各出版社のセクション、次に各著者のセクションにアクセスして、適切な色の本を見つける必要があります。そのため、本が色でソートされていると一気に言うことができたとしても、「インデックス」は色でスキャンするのにはあまり適していません。

最後のインデックスを追加するとRECEIPT_ID、クエリをで制限しているため、並べ替えて使用できますSUBTYPE。したがってRECEIPT_ID、両側からのすべての値が単純に利用可能であり、コストが低く、マージ結合が選択されます。

于 2012-08-23T14:37:48.103 に答える