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


10

気になるだけです。

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

select order_value from store.orders

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

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


これに関するたくさんの情報がウェブ上にあります。重要なのは、テクノロジーの変化に応じて最新の情報を取得することです。あなたが求めていることはあなたの特定のセットアップに非常に依存しているので、非常に良い答えを与えることは不可能です。覚えておくべき重要な点は、SSDに移行すると、かつてパフォーマンスにとって非常に重要であった多くのことはもはや当てはまらないということです。
Joe

回答:


10

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

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

ナッツ

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時間を少し節約できます。

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

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

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

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


@ jpmc26リクエストされた列がすべてインデックスの一部である場合、クエリはインデックスを見るだけで処理できるため、それよりも悪くなる可能性があります。列にインデックスが付けられていない場合、プライマリレコードが読み込まれる可能性があります。
クリストファーシュルツ

12

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

  • ケースA:共通(行ストア)テーブル(order_value)

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

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

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

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

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


私の知識は、この問題について少しグリーンです。行ストアテーブルを持つのは最も一般的な(たとえば、典型的なSQL Serverデータベース)ですよね?列/フィールドを1つだけ返す必要がある場合、なぜテーブル全体がスキャンされるのですか?これは、行ストアテーブルの設計に固有のものですか?
user45867 2017年

@ user45867はい、データは行に格納されます(外部に格納される非常に大きな列を除く)。SQL Serverがディスクから読み取る場合、ブロック全体を読み取り、1列の部分のみを読み取ることはできません。
ypercubeᵀᴹ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.