web-dev-qa-db-ja.com

関連しない列は、selectステートメントのクエリ時間に影響しますか?

気になるだけです。

100万レコード/行のテーブルがあるとします。

select order_value from store.orders

そのテーブルに実際のクエリ時間で1フィールド、2フィールド、または100フィールドがあるかどうかに違いはありますか? 「order_value」以外のすべてのフィールドを意味します。

現在、私はデータウェアハウスにデータをプッシュしています。 「将来、いつか使用される可能性がある」フィールドをテーブルにダンプすることもありますが、現在、なんらかの方法でクエリされていません。これらの「無関係な」フィールドは、それらを含まないselectステートメントに直接または間接的に影響しますか(いいえ*意味します)?

10
user45867

これは実際にはインデックスとデータ型に依存します。

例としてStack Overflowデータベースを使用すると、Usersテーブルは次のようになります。

NUTS

Id列にPK/CXがあります。つまり、Idでソートされたテーブルデータ全体です。

それが唯一のインデックスである場合、SQLは(LOB列を削除して)その全体をメモリに読み込まなければなりません(まだそこにない場合)。

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SET STATISTICS TIME, IO ON 

SELECT u.Id
INTO  #crap1
FROM dbo.Users AS u

統計の時間とioのプロファイルは次のようになります。

Table 'Users'. Scan count 7, logical reads 80846, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2406 ms,  elapsed time = 446 ms.

Idだけに追加の非クラスター化インデックスを追加した場合

CREATE INDEX ix_whatever ON dbo.Users (Id)

これで、クエリを満たす非常に小さなインデックスができました。

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SELECT u.Id
INTO  #crap2
FROM dbo.Users AS u

ここのプロフィール:

Table 'Users'. Scan count 7, logical reads 6587, physical reads 0, read-ahead reads 6549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2344 ms,  elapsed time = 384 ms.

読み取り回数を大幅に減らし、CPU時間を少し節約できます。

テーブル定義に関する詳細情報がないと、測定しようとしているものをより正確に再現することはできません。

しかし、その唯一の列に特定のインデックスがない限り、他の列/フィールドもスキャンされると言っていますか?これは、行ストアテーブルの設計に固有の欠点ですか?無関係なフィールドがスキャンされるのはなぜですか?

はい、これは行ストアテーブルに固有です。データは、データページの行ごとに格納されます。ページ上の他のデータがクエリに関係ない場合でも、行全体>ページ>インデックスをメモリに読み込む必要があります。他の列が「スキャン」されているとは言いませんが、それらの列が存在するページがスキャンされ、クエリに関連するそれらの単一の値を取得するためです。

古い電話帳の例を使用すると、電話番号を読んでいるだけの場合でも、ページをめくると、姓、名、住所などが電話番号とともに表示されます。

10
Erik Darling

これは、テーブルの構造と使用可能なインデックスによって異なります。

  • ケースA:共通(行ストア)テーブル、(order_value)にインデックスがありません。

    考えられる唯一の実行プランは、テーブル全体を読み取ることです(もちろん、2カラムと200カラムの場合、数バイトと数千バイトの幅は大きく異なります)。

  • ケースB:共通テーブル。(order_value)またはその列を含む他のいくつかのインデックスにインデックスがあります。

    今より良い計画があります。インデックス全体(そのうちの1つ)をスキャンします。これはもちろん、テーブル全体よりもはるかに狭い数バイトです。これは、テーブルに2列または200列がある場合は無関係です。インデックスのみがスキャンされます。

  • ケースC:列ストアテーブルです。

    名前が示すように、これらのテーブルの構造は列方向であり、行方向ではありません。インデックスは必要ありません。テーブルデザイン自体は列全体を読み取るのに適しています。

12
ypercubeᵀᴹ