2011-01-03 7 views
9

データベースの列型の順序はクエリ時間に影響しますか?列の順序に基づくクエリ速度

たとえば、連続した型(INT、INT、VARCHAR、TEXT、TEXT)を持つ表よりも、混合順序(INT、TEXT、VARCHAR、INT、TEXT)の表の方が処理速度が遅くなりますか?

答えて

8

答えははいです。それは大したことですが、 通常はです。

すべてのI/Oはページレベルで実行されます(OSによっては通常2Kまたは4K)。行の列データは、ページがいっぱいになった場合を除いて、隣り合って格納されます。この場合、データは別のページ(通常は次のページ)に書き込まれます。

(テーブル定義に基づいて)選択した列間の列に必要なディスク上のデータ容量が大きいほど、選択した列のデータが(時には)異なるページに表示される可能性が高くなります。別のページにいると、余分なI/O操作が発生する可能性があります(他のページで他の行が選択されていない場合)。最悪の場合、選択する各列は別のページにある可能性があります。ここで

は例です:

create table bad_layout (
num1 int, 
large1 varchar(4000), 
num2 int, 
large2 varchar(4000), 
num3 int, 
large3 varchar(4000) 
); 

create table better_layout (
num1 int, 
num2 int, 
num3 int, 
large1 varchar(4000), 
large2 varchar(4000), 
large3 varchar(4000) 
); 

は比較: NUM1、NUM2、bad_layoutからNUM3を選択します。 num1、num2、num3をbetter_layoutから選択します。

bad_layoutのために、各num列は基本的に別のページに置かれるため、各行には3回の入出力操作が必要です。逆に、better_layoutのnum列は通常同じページにあります。

bad_layoutクエリは、実行に約3倍かかることがあります。

テーブルのレイアウトが適切であると、クエリのパフォーマンスが大きく変わる可能性があります。テーブルレイアウトでは、通常一緒に選択されている列を互いにできるだけ近くに保つようにしてください。

+0

これは意味があります。誰かがそれをテストする気になるでしょうか? PostgreSQLのインストールは便利ではありません。 –

+0

[TOAST](http://www.postgresql.org/docs/9.4/static/storage-toast.html)は、大きな列の値がこの種の問題を引き起こすのを防ぐことはできませんか?さらに、そのドキュメント(私が正しく読んでいる場合)は、行タプルが複数のページにまたがっていることを明示的に述べています。 – jpmc26

5

この順番はあまり重要ではありません。実行時間はディスクアクセス時間などによって左右され、行内のデータを並べ替えた結果、ディスクアクセスの回数と順序が変わることはほとんどありません。

1つの例外は、行内に非常に大きなアイテム(ディスクブロックよりも大きく、通常は4K?)がある場合です。テーブルに1つの非常に大きな列がある場合は、最後の列として配置することで、アクセスしない場合は完全にページインする必要はないかもしれません。しかし、その場合でも、違いが目立つようなデータセットとアクセスパターンを生成するのはかなり困難です。

+1

実際に私が選択していない真ん中の「大きな」列でさえ違いはないと思います。もしそれが大きければ、とにかくトーストされるでしょう。したがって、実際の列データは通常のテーブルブロックには存在せず、列が選択されていない場合はTOASTテーブルには触れません。 –

3

PostgreSQLでは、アクセスパスが特別に最適化されているため、固定幅カラムを最初に置くと利点があります。したがって、(INT、INT、VARCHAR、TEXT、TEXT)は最も速くなります(VARCHARとTEXTの相対的な順序は関係ありません)。

また、型の配置要件を正しく管理すると、領域を節約でき、処理量とパフォーマンスが向上します。たとえば、(INT、BOOL、INT、BOOL)は13バイトのスペースを必要とします。なぜなら、3番目のカラムは4バイトの境界に揃えなければならないため、2番目と3番目のカラムの間に3バイトのスペースが無駄になります。ここでは(INT、INT、BOOL、BOOL)が良いでしょう。 (この行の後に来るものは、おそらく少なくとも4バイトのアラインメントが必要なので、最後に2バイトを無駄にするでしょう)。

+1

これはinteresstingなので、それは分かりませんでした。このトピックへの参照はありますか? – DrColossos

+1

これは主に私のソースコードの知識です。あなたがそれに潜入したいなら 'fastgetattr'を探してください。 –

+0

私はこれを証明する実例を見たいと思っています。これはコードに基づいていますが違いはありますか?現実世界では実際に差異タイプのことに気づくことはありませんか?多分余裕を持って私は例を挙げて遊び、できるならば投稿します。 – Kuberchaun

0

どのように列を注文しても、大きな違いはないことを私は示唆しています。

のPostgreSQL:http://social.msdn.microsoft.com/Forums/en-US/sqldatabaseengine/thread/a7ce8a90-22fc-456d-9f56-4956c42a78b0

SQL Serverの: http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/36713a82-315d-45ef-b74e-5f342e0f22fa

私は、MySQLのために同じことを疑います。

すべてのデータはページ単位で読み込まれるため、データが1ページに収まる場合は、どのように列を並べるかは関係ありません。ディスクブロックサイズが2K、4Kの場合、「8Kページ要求」を満たすために複数のブロックサイズが使用されます。ディスクブロックサイズが64K(大規模なDBシステムの場合)の場合は、すでに他のデータをバッファしています。

だけでなく、レコードが要求された場合、データが複数のページにまたがる場合は、ページ2とページ3へのオーバーフローを含め、レコードのすべてのページを通常取得します。次に、検索されたデータから列が計算されます。 SQL Serverには、約8060バイトのページ内データに制限があります。より大きなものは、PostgreSQLのTOASTと同様に、メインのデータページに保存され、カラムが使用されない場合は取り出されません。 まだは、列がどこにあるかは関係ありません。

たとえば、SQL Serverでは、複数のビットフィールドがビットパターンのマスクにまとめて格納されます。これは、列を互いに並べるかどうかにかかわらずです。私は、MySQLとPostgreSQLが空間を最適化するために同じことをすると思われます。

注:[重要] - この資格の唯一の理由は、データページから特定の列を抽出する場合、低レベルのアセンブリ呼び出しがシークする必要がないためですメモリブロックのはるか遠い。

関連する問題