web-dev-qa-db-ja.com

SQL Serverがメモリ内のデータをキャッシュする方法

データのキャッシュのしくみについていくつか質問があります
以下の状況を想像してください:

サーバーが再起動されたか、実行されましたDBCC DROPCLEANBUFFERS

Table1 50 GBで、列ABCDEがあります。
Aはクラスター化インデックスキーであり、列BおよびCには非クラスター化インデックスがあります。

  1. 私たちがするとき

    select top 100 * from Table1
    

    100行しか必要ない場合でも、クラスター化インデックス全体(テーブル)がディスクからメモリに読み取られていますか?または、100行(データページ)がディスクからメモリに読み取られますか?

  2. 実行すると、非クラスター化インデックスと同じ

    select top 100 * from Table1 where column B = 'some value'
    

    非クラスター化インデックス+クラスター化インデックス全体がメモリに読み込まれますか?または、非クラスター化インデックスの100行とクラスター化インデックスの100行だけですか?

6
Aleksey Vitsko

テストデータ

CREATE TABLE dbo.Table1( A INT IDENTITY(1,1) PRIMARY KEY NOT NULL
                     ,B varchar(255),C int,D int,E  int);

INSERT  INTO dbo.Table1 WITH(TABLOCK)
(B,C,D,E)

SELECT TOP(1000000) 'Some Value ' + CAST((ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) % 400) as varchar(255))-- 400 different values
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM master..spt_values spt1
CROSS APPLY master..spt_values spt2;

CREATE INDEX IX_B
On dbo.Table1(B);
CREATE INDEX IX_C
On dbo.Table1(C);

Q1

「表1から上位100 *を選択」を実行すると、クラスター化インデックス(テーブル)全体がディスクからメモリに読み込まれます。または、100行(データページ)がディスクからメモリに読み込まれますか?

クラスター化インデックスから100行のみが読み取られます。その結果、データページのみがメモリにキャッシュされます。

私の場合、クラスタードインデックスから下向きに読み取られ、列Aの値は1〜100です。

SET STATISTICS IO, TIME ON;
select top 100 * from dbo.Table1

読み取り:

Table 'Table1'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

4論理読み取り= 4ページ

なぜまだscan count = 1、 だけ 4論理読み取りは、あなたが尋ねるかもしれませんか?

範囲スキャンを実行しているため:

enter image description here

enter image description here

最上位の演算子を満たすため。


Q2

非クラスター化インデックスと同様に、「列B = '値'であるTable1から上位100 *を選択」を実行すると、非クラスター化インデックス全体+クラスター化インデックスがメモリに読み込まれますか?または非クラスタ化インデックスから100行+クラスタ化インデックスから100行?

例1

SET STATISTICS IO, TIME ON;
select top 100 * from dbo.Table1
WHERE B='Some Value 200'

ここでは非クラスター化インデックスが使用されることが予想されますが、実際にはクラスター化インデックスが引き続き使用されます。

enter image description here

キャッシュをクリアした後287論理読み取り&2528先読み。

Table 'Table1'. Scan count 1, logical reads 287, physical reads 1, read-ahead reads 2528, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

これらの先読み読み取りをディスクから読み取り、次に287メモリからのページ。

先読みメカニズムはSQL Serverの機能であり、クエリによってデータが要求される前でも、データページをバッファキャッシュに取り込みます。 ソース

キャッシュされたページをチェックした場合:

cached_pages_count  objectname  indexname   indexid
2536    Table1  PK__Table1__3BD019AE039DA497    1

これも表示されています。

したがって、この場合は、より多くのページをキャッシュしてクエリにすばやく対応します。これは、残りの述語を適用するためにより多くの行を読み取るためです。

enter image description here

ただし、これらのページはclusteredインデックスからのみ読み取っています。

例2

非クラスター化インデックスを利用することを期待して、クエリを変更できます。

select top 100 B from dbo.Table1
WHERE B='Some Value 200';

それはどちらですか:

enter image description here

これも小さな範囲スキャンを提供します:

Table 'Table1'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

ここでは、nonclusteredインデックスページのみがメモリに読み込まれます。

例3

インデックスヒントを使用して、例1のクエリを満たすようにキー検索を強制できます。

SET STATISTICS IO, TIME ON;
select top 100 * 
from dbo.Table1
WITH(INDEX(IX_B))
WHERE B='Some Value 200';

これにより、先読みがいくつか発生し、example1よりも論理的な読み取りが多くなります。

Table 'Table1'. Scan count 1, logical reads 684, physical reads 3, read-ahead reads 465, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

非クラスター化からクラスター化インデックスへのキールックアップを行っているので、両方のインデックスのページをキャッシュします。

enter image description here

8
Randi Vertongen

100行だけが必要な場合でも?または100行(データページ)がディスクからメモリに読み込まれますか?

TOP句が論理シーケンスの最後に考慮されるため、SQLクエリの論理処理順序が原因である可能性があります。 詳細については.. 。したがって、WHERE句にフィルターを適用すると、TOP 100を適用せずに100行のみを返すと、読み取られるページが少なくなります。

3
Shekar Kola