SQL Server 2012での2つのクエリの比較


14

SQL Server 2012の2つのクエリを比較しています。目標は、最適なクエリを選択するときに、クエリオプティマイザーから利用可能な関連情報をすべて使用することです。両方のクエリは同じ結果を生成します。すべての顧客の最大注文ID。

FREEPROCCACHEおよびDROPCLEANBUFFERSを使用して各クエリを実行する前に、バッファプールをクリアしました

以下の情報を使用して、どのクエリがより良い選択ですか?

-- Query 1 - return the maximum order id for a customer
SELECT orderid, custid
FROM Sales.Orders AS O1
WHERE orderid = (SELECT MAX(O2.orderid)
                 FROM Sales.Orders AS O2
                 WHERE O2.custid = O1.custid);


-- Query 2 - return the maximum order id for a customer
SELECT MAX(orderid), custid
FROM Sales.Orders AS O1
group by custid
order by custid

統計時間

クエリ1の統計時間:CPU時間= 0ms、経過時間= 24ms

クエリ2の統計時間:CPU時間= 0ミリ秒、経過時間= 23ミリ秒

統計IO

クエリ1の統計IO:テーブル「注文」。スキャンカウント1、論理読み取り5、物理読み取り2、先読み読み取り0、lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0

クエリ2の統計IO:テーブル「注文」。スキャン数1、論理読み取り4、物理読み取り1、先読み読み取り8、lob論理読み取り0、lob物理読み取り0、lob先読み読み取り0

実行計画

ここに画像の説明を入力してください

SELECTプロパティクエリ1

ここに画像の説明を入力してください

SELECTプロパティクエリ2

ここに画像の説明を入力してください

結論:

クエリ1

  1. バッチ費用48%
  2. 論理読み取り5
  3. 物理読み取り2
  4. 先読み読み取り:0
  5. CPU時間:0ミリ秒
  6. 経過時間24ms
  7. 推定サブツリーコスト:0.0050276
  8. CompileCPU:2
  9. CompileMemory:384
  10. CompileTime:2

クエリ2

  1. バッチ費用52%
  2. 論理読み取り4
  3. 物理的な読み取り1
  4. 先読み読み取り:8
  5. CPU時間0
  6. 経過時間23ms
  7. 推定サブツリーコスト:0.0054782
  8. CompileCPU:0
  9. CompileMemory:192
  10. CompileTime:0

個人的には、クエリ2のグラフィカルプランによるとバッチコストは高くなりますが、クエリ1よりも効率的だと思います。低い。先読み読み取りは、クエリ2の場合は8、クエリ1の場合は0です。

更新12:03

クラスター化インデックスの定義

ALTER TABLE [Sales].[Orders] ADD  CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
    [orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

非クラスター化インデックスidx_nc_custid

CREATE NONCLUSTERED INDEX [idx_nc_custid] ON [Sales].[Orders]
(
    [custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ポールホワイト9

回答:


10

クエリのチューニングとオプションと計画の確認を慎重に検討するアプローチが大好きです。より多くの開発者がこれをしたことを望みます。注意点の1つは、論理読み取りを見て、常に多くの行でテストすることです。これは小さなテーブルです。サンプルロードを試行して生成し、クエリを再実行してください。1つの小さな問題-あなたの一番上のクエリでは、あなたはあなたの一番下のクエリで注文を求めていません。それぞれを順序付けて比較および対比する必要があります。

200,000件の販売注文を含むSalesOrdersテーブルをすぐに作成しましたが、想像力の限りではまだ巨大ではありません。そして、それぞれにORDER BYを指定してクエリを実行しました。また、インデックスを少し使用しました。

OrderIDにクラスター化インデックスがなく、CustIDに非クラスター化インデックスがある場合 2番目のクエリのパフォーマンスが向上しました。特に、それぞれに含まれる順序で。最初のクエリの読み取りは2番目のクエリの2倍であり、コストの割合はクエリ間で67%/ 33%でした。

OrderIDのクラスター化インデックスとCustIDの非クラスター化インデックスを使用して、同様の速度とまったく同じ読み取り数で実行しました。

したがって、行数を増やして、さらにテストを行うことをお勧めします。しかし、あなたのクエリに関する私の最終的な分析-

行を増やしたときに気付くよりも似た振る舞いをすることがありますので、その点に注意してテストしてください。

返されるすべてが各顧客の最大OrderIDであり、OrderIDが最大のOrderIDであると判断したい場合、これら2つのうちの2番目のクエリが私の考え方からの最善の方法です-それは少しですより単純で、サブツリーのコストに基づいてこれまでよりも少し高価ですが、ステートメントを解読するのがより迅速で簡単です。いつか他の列を結果セットに追加するつもりですか?次に、最初のクエリでそれを行うことができます。

更新: 質問の下でのコメントの1つは次のとおりです。

この質問で最適なクエリを見つけることは、それらを比較するために使用される技術を改良する手段であることに留意してください。

しかし、より多くのデータを使用してそのテストを実行するための最善の方法は、常に本番および予想される将来の本番と一貫したデータを確保することです。クエリプランは、テーブルにさらに行を追加するとデータの検索を開始し、実稼働で期待される分散を維持しようとします。そして、Order Byを含むかどうかなどに注意してください。ここでは、それが最終的にひどい違いを生むとは思いませんが、まだ掘り下げる価値があります。

このレベルの詳細とデータを比較するアプローチは良い方法です。サブツリーのコストはほとんど任意であり、ほとんど意味がありませんが、編集/変更間またはクエリ間で比較するために少なくとも検討する価値があります。時間統計とIOを確認することは非常に重要です。また、作業しているデータのサイズと何をしようとしているかについて不適当であると思われるものの計画を確認することも重要です。


こんにちは、大量のデータを使用することについてのあなたのポイントに感謝します。誰かがそれを持ち出したのはこれが初めてではありません。前回は、ページ分割によるフラグメンテーションの可能性を考慮することでした。200,000行のサンプルで、断片化をチェックしましたか?
クレイグエフライン

私の小さな200k行の小さな例では、断片化に焦点を合わせていませんでした。しかし、私がそれをした方法は何もありませんでした。テーブルを作成し、データを入力してからインデックスを作成したので、それらは新しく作成されたインデックスでした。そして、それは主要な質問であると思われるクエリプランを見るアプローチを変えません。クエリプランを正確に見ると、データの量は非常に大きくなります。私はよく(1〜10行の)devで見栄えがよく、実際のデータを使用してprodで恐ろしいケースを見てきました。しかし、あなたのアプローチが良いですし、うまくいけば、この情報およびコメントで会話ができます
マイク・ウォルシュ

custidでグループ化しているので、どのようにしてcustid値を十分にランダムにしましたか?読書から覚えていることの1つは、明確な価値の重要性です。custidに少数の顧客しかいない場合、ストリーム集約のコストは非現実的です。
クレイグエフライン

RAND関数を使用して100人の顧客を作成し、各注文IDにランダムに1人を割り当てました。:)
マイクウォルシュ

マイクに助けてくれてありがとう。最後の質問です。質問で提供した2012年の実行計画のSELECTプロパティ画面から、どの値に注意を払っていますか?
クレイグエフレイン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.