2

最近、SELECTクエリでデータを並べ替えるパターン(確かではありませんが、アンチパターンである可能性があります)に出くわしました。このパターンは、データを順序付けるためのより冗長で非宣言的な方法です。パターンは、関連データを実際のテーブルから一時テーブルにダンプしてから、一時テーブルのフィールドにorderbyを適用することです。私が思うに、誰かがそれをする唯一の理由は、パフォーマンスを改善することであり(私は疑っています)、他の利点はありません。

たとえば、ユーザーテーブルがあるとします。テーブルには、数百万の行が含まれる場合があります。名が「G」で始まり、名でソートされているすべてのユーザーを取得する必要があります。このシナリオのSQLクエリを実装するための自然で宣言的な方法は次のとおりです。

より自然で宣言的な方法

SELECT * FROM Users
WHERE NAME LIKE 'G%'
ORDER BY Name

冗長な方法

SELECT * INTO TempTable
FROM Users
WHERE NAME LIKE 'G%'

SELECT * FROM TempTable
ORDER BY Name

その文脈で、私はいくつかの質問があります:

  1. 名フィールドにインデックスがない場合、2つの方法の間にパフォーマンスの違いはありますか?はいの場合、どちらが良いでしょう。

  2. 名フィールドにインデックスがある場合、2つの方法の間にパフォーマンスの違いはありますか?はいの場合、どちらが良いでしょう。

  3. SQL Serverオプティマイザーは、両方の方法で同じ実行プランを生成するべきではありませんか?

  4. ロック/ブロッキングのような他のパースペクティブから冗長な方法を書くことに何か利点はありますか?

前もって感謝します。

4

3 に答える 3

1

Reguzlarly:何をしているのかわからない人々によるアンチパターン。

時々:わかりました。SQLServerには、他の方法では解決できない問題があるためです。ただし、問題は発生していません。

tmpddbテーブルが最初に完全に入力されるように強制されるため、処理が遅くなりますが、そうでない場合は、クエリをより効率的に解決できる可能性があります。

前回見たのは3年前のようなものでした。スマートではなく、tempdbテーブルを使用することで、3倍の速度で取得できました;)

回答:

1:いいえ、明らかに、まだテーブルスキャンが必要です。

2:おそらく-データ量によって異なりますが、インデックスによるインデックスシークには、すでにデータが順番に含まれています(インデックスはコンテンツ順に並べられているため)。

3:いいえ。明らかに。クエリプランの最適化は、ステートメントごとです。実行を2にカットすることにより、クエリオプティマイザは結合を最初のステートメントにマージできません。

4:クエリオプティマイザの問題または結合できるテーブル数の制限に遭遇した場合のみ-その縮退の場合ではありません(技術的な意味で縮退-つまり非常に単純です)。ただし、多数のテーブルを結合する必要がある場合は、暫定的な手順を実行する方がよい場合があります。

于 2012-06-26T13:05:20.853 に答える
0

私が考えることができる2番目のアプローチの利点は決してありません。

これは、データが利用可能な場合、事前に注文されたSQL Serverはこれを利用できず、不要なブロッキング演算子と追加の並べ替えをプランに追加することを意味します。

データが利用できない場合、事前に注文されたSQL Serverは、メモリ内またはtempdbとにかく作業テーブルでデータを並べ替えます。明示的な#tempテーブルを追加すると、不要な追加手順が追加されます。

編集

2番目のアプローチが明らかな利点をもたらす可能性がある1つのケースは、ORDER BY原因となったSQL Serverの存在によって、最適ではないことが判明した別のプランを選択した場合であると思います。その場合、統計を改善するか、ヒント/クエリの書き換えを使用して望ましくない計画を回避することにより、別の方法でそれを解決します。

于 2012-06-26T13:31:18.123 に答える
0

順序付けを行うフィールドにインデックスが付けられていない場合は、すべてを一時テーブルに入れてインデックスを付けてから順序付けを行うと、より高速になる可能性があります。確認するためにテストする必要があります。

于 2012-06-26T13:42:49.467 に答える