web-dev-qa-db-ja.com

「order by」列を追加すると、はるかに悪い計画になります

言い換えれば、下の画像のsort演算子を取り除くにはどうすればよいですか?

enter image description here

上の画像 次の2つの選択の実行プランを一緒に示します

                SELECT   TOP 1 so.OrgType, 
                              ch.Status, 
                              rcs.DBSstatusDescription, 
                              cid.ApplicationId
                   FROM   tbl_application_crb_initialData cid

                   INNER JOIN  tbl_season_organisationId so
                          ON   cid.OrganisationId = so.OrgId

                   LEFT JOIN  tbl_crbHistory ch  
                          ON  cid.ClientReference = ch.ClientReference

                   LEFT JOIN  ref_crbStatus rcs
                         ON   ch.Status = rcs.statusId    

                   ORDER BY  cid.DateAdded DESC, ch.DateAdded DESC

                SELECT   TOP 1 so.OrgType, 
                              ch.Status, 
                              rcs.DBSstatusDescription, 
                              cid.ApplicationId
                   FROM   tbl_application_crb_initialData cid

                   INNER JOIN  tbl_season_organisationId so
                          ON   cid.OrganisationId = so.OrgId

                   LEFT JOIN  tbl_crbHistory ch  
                          ON  cid.ClientReference = ch.ClientReference

                   LEFT JOIN  ref_crbStatus rcs
                         ON   ch.Status = rcs.statusId    

                   ORDER BY  cid.DateAdded DESC--, ch.DateAdded DESC

唯一の違いは、2番目のクエリでは、順番に1つの列しかないことです。

top 1を使用しているので、違いはありますか?

必要な情報はすべて、インデックスとテーブルの定義にあると思います クエリプランで確認できます

それを取り除くために他に役立つものがある場合は、sortにお知らせください。明日、可能な限りの情報をすべて投稿します。

3

あなたの質問には多くの詳細がありませんが、私は同様のものを再現できます。

セットアップ

CREATE TABLE T1(X INT PRIMARY KEY, Y INT INDEX IX)

CREATE TABLE T2(X INT, Y INT , PRIMARY KEY(X, Y))

INSERT INTO T2 
OUTPUT INSERTED.* INTO T1
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM sys.all_objects o1, sys.all_objects o2;

クエリ1

SELECT TOP 1 T1.Y AS T1Y, T2.Y AS T2Y
FROM T1 JOIN T2 ON T1.X = T2.X 
ORDER BY T1.Y;

enter image description here

クエリ2

SELECT TOP 1 T1.Y AS T1Y, T2.Y AS T2Y
FROM T1 JOIN T2 ON T1.X = T2.X 
ORDER BY T1.Y, T2.Y

enter image description here

クエリ3

WITH T  AS
(
SELECT TOP 1 WITH TIES T1.Y AS T1Y, T2.Y AS T2Y
FROM T1 JOIN T2 ON T1.X = T2.X 
ORDER BY T1.Y
)
SELECT TOP 1 *
FROM T 
ORDER BY T2Y

enter image description here

クエリ1は、インデックスからTOP 1を目的の並べ替え順序で取得し、その行の他のテーブルで必要な結合を実行します。結合が成功した場合、そこで停止します。それ以外の場合は、行が一致するか行がなくなる行が見つかるまで、インデックス順に次の行を試行します。

Query 2新しい並べ替え列を追加すると、TOP 1値とSQL Serverに関連付けられた複数の一致が存在する可能性があるため、このプランは無効になりますロット全体に参加することを決定し、それからTOP 1を取得します。

Query 3これにより、SQL Serverは最初の戦略を忠実に守り、同じ値に関連付けられているすべての行に対してTOP 1 Sortを実行します。最初のソートキー。

私の例のデータの場合、クエリ3はクエリ2よりもうまく機能しますが、最初のソートキーの値に関連付けられた多くの重複がある場合、走行距離は異なる場合があります。

あなたはこの書き直しを試して、それがどれほどの運賃かを見ることができます

WITH T
     AS (SELECT TOP 1 WITH TIES so.OrgType,
                                ch.Status,
                                rcs.DBSstatusDescription,
                                cid.ApplicationId,
                                ch.DateAdded AS chDateAdded
         FROM   tbl_application_crb_initialData cid
                INNER JOIN tbl_season_organisationId so
                        ON cid.OrganisationId = so.OrgId
                LEFT JOIN tbl_crbHistory ch
                       ON cid.ClientReference = ch.ClientReference
                LEFT JOIN ref_crbStatus rcs
                       ON ch.Status = rcs.statusId
         ORDER  BY cid.DateAdded DESC)
SELECT TOP 1 OrgType,
             Status,
             DBSstatusDescription,
             ApplicationId
FROM   T
ORDER  BY chDateAdded DESC 
8
Martin Smith