web-dev-qa-db-ja.com

SELECTクエリのデフォルトの行順序-SQL Server 2008とSQL 2012

私たちのチームは最近、データベースをSQL Server 2008からSQL Server 2012にアップグレードしました。私たちが気付いた1つの重大な変更は、SELECTステートメントによって返される行のデフォルトの順序、つまり明示的なORDER BY句が指定されていない場合でした。

MSDNによると、 SQL Server 2012 は、ORDER BY句が指定されていない限り、返される行の順序を保証しません。

ORDER BY句のないSELECTステートメントを含む5つのデータベースにわたって2500以上のストアドプロシージャがあり、SQL Server 2008の動作と一致するようにORDER BY句を手動で追加するのはかなりの労力になります。設定またはより高速な方法はありますか?この?

まだ検討されていないもう1つのオプションは、SQL Server 2008にダウングレードすることです。これはどれほど難しいでしょうか。

12
Channs

戻ってORDER BY句をコードに追加する必要があります。これらの句がないと、順序が保証されないためです。以前は常に同じ注文を受けたことが「幸運」でしたが、SQL Server 2008がとにかくそれを保証していたので、そうではありませんでした。ほとんどの場合、それはインデックスまたはデータがディスクに格納されていた方法に関係しています。

ハードウェア構成の違いだけをアップグレードしたときに新しいホストに移動した場合、クエリの実行方法が変更された可能性があります。新しいサーバーがテーブルの統計を再計算し、SQL Server 2012クエリオプティマイザーがSQL Server 2008のものとは少し異なる動作をすることは言うまでもありません。

希望する順序を明示的に指定せずにSQLで結果セットの順序に依存できるのは誤りです。SQL結果[〜#〜]決して[〜#〜]ORDER BY句を使用せずに信頼できる順序があります。 SQLは集合論に基づいて構築されています。クエリ結果は基本的にセット(またはマルチセット)です。

Itzik Ben-Ganは、彼の著書でSQLに関連する集合論の優れた説明を提供しています Microsoft SQL Server 2012 T-SQL Fundamentals

数学者Georg Cantorを起源とする集合論は、関係モデルの基礎となる数学的分岐の1つです。 Cantorのセットの定義は次のとおりです。

「集合」とは、私たちの知覚または思考の明確な別個のオブジェクトm(Mの「要素」と呼ばれる)へのコレクションMを意味します。 -ジョセフW.ドーベンとジョージカントール(プリンストン大学出版局、1990年)

定義の用語の完全な説明の後、Itzikは次のように続けます:

Cantorのセットの定義が除外しているものは、おそらくそれが含むものと同じくらい重要です。定義では、セット要素間の順序について言及されていないことに注意してください。セット要素がリストされる順序は重要ではありません。セット要素をリストするための正式な表記では、中括弧{a、b、c}を使用します。順序には関連性がないため、{b、a、c}または{b、c、a}と同じセットを表すことができます。リレーションのヘッダー(SQLではテーブルと呼ばれます)を構成する一連の属性(SQLでは列と呼ばれます)にジャンプすると、要素は順序位置ではなく名前で識別されます。同様に、リレーションの本体を構成するタプルのセット(SQLでは行と呼ばれます)を検討してください。要素は、位置ではなくキー値によって識別されます。多くのプログラマーは、テーブルのクエリに関して、行間に順序がないという考えに適応するのに苦労しています。 つまり、データを特定の方法で並べ替えることを明示的に要求しない限り、テーブルに対するクエリは、任意の順序で行を返すことができます。おそらくプレゼンテーションの目的で。

しかし、セットの学術的な定義に関係なく、SQLサーバーの実装でさえ、結果の順序が保証されていません。この クエリオプティマイザーチームのメンバーによる2005年のMSDNブログ投稿 は、中間操作からの順序にまったく依存してはならないことを述べています。

並べ替え規則は、この仮定に違反する可能性があり、違反します(開発者であるあなたにとって不便な場合はそうです)。より効率的な計画を見つけるために操作を並べ替えると、ツリーの中間ノードの順序付け動作が変わる可能性があることを理解してください。特定の中間の順序を前提とする操作をツリーに配置した場合、操作が失敗する可能性があります。

Conor Cunningham(Architect、SQL Server Core Engine)によるこのブログ投稿 " No Seatbelt-Expecting Order without ORDER BY "は、SQL Server 2008に関するものです。それは常に同じ順序で行を返すようです。 ORDER BYをクエリに追加しても、実行プランは変更されないため、オプティマイザが必要としない場合にクエリを追加するとクエリがより高価になるわけではありません。しかし、彼がテーブルに別の20k行を追加すると、突然クエリプランが変更され、並列処理が使用され、結果は順序付けられなくなります

ここで難しいのは、計画がいつ変更されるかを外部ユーザーが知る合理的な方法がないことです。すべての計画のスペースは巨大であり、熟考するのに頭が痛いです。 SQL Serverのオプティマイザは、単純なクエリの場合でも、十分なパラメータが変更されると、計画を変更します。幸運にも計画が変更されないか、この問題について考えずにORDER BYを追加することができます。

もっと説得力が必要な場合は、これらの投稿を読んでください:

42
Mike D.