web-dev-qa-db-ja.com

SQL Server列ストアメタデータ(プッシュダウン)フィルター

AFAIK列ストアインデックスはセグメント(100万行)の最小値/最大値を格納するため、この情報を使用して不要なデータを削除できます。この機能は、等価述語では機能するようですが、結合やサブクエリフィルターなどのより複雑なケースでは機能しません。 SQL Server 2014では、結合またはサブクエリで列ストアメタデータフィルタリングを使用できますか?

以下は私のテストケースです:

--create table generate_series with 67_108_864 rows (runs about 5 mins)

set nocount on;

create table generate_series(c bigint);
insert into generate_series select 1;

declare @i int = 26;
while @i != 0
begin
    insert into generate_series WITH (TABLOCK)
    select
        (select count(*) from generate_series)
        + row_number() over (order by (select null)) as c
    from generate_series;

    set @i = @i - 1;
end;


create nonclustered columnstore index cstore on generate_series(c);


--Test queries

-- 0 seconds (very fast)
select * from generate_series where c = 100;

-- 8 seconds (slow)
select 100 as c into #tmp;
select * from generate_series where c in (select c from #tmp);
3
Alex

あなたが説明しているパフォーマンスの最適化は 行グループの除去 として知られています。 SQL Server2016とSQLServer 2014の両方で両方のクエリを使用して行グループを削除できますが、SQL Server2014には追加の制限があります。

まず、SQL Server2016でテストしてみましょう。次のクエリは非常にすばやく終了します。

select * 
from generate_series 
where c = 100
OPTION (MAXDOP 1);

SQL Server 2016は、SET STATISTICS IO ON;を介して行グループの削除に関する追加の診断情報を提供するので、それを利用しましょう。

テーブル 'generate_series'。セグメント読み取り1、セグメントスキップ68。

SQL Serverの実行時間:CPU時間= 0ミリ秒、経過時間= 9ミリ秒。

このクエリも高速です。

select * 
from generate_series 
where c in (select c from #tmp)
OPTION (MAXDOP 8);

統計出力:

テーブル 'generate_series'。セグメント読み取り1、セグメントスキップ68。

SQL Serverの実行時間:CPU時間= 0ミリ秒、経過時間= 11ミリ秒。

このクエリも高速です。

select * 
from generate_series 
where c in (select c from #tmp)
OPTION (MAXDOP 1);

テーブル 'generate_series'。セグメント読み取り1、セグメントスキップ68。

SQL Serverの実行時間:CPU時間= 0ミリ秒、経過時間= 5ミリ秒。

クエリごとに、SQLServerは68行グループをスキップできます。 IDが100の行グループからのみデータを読み取ります。最終クエリの計画では、最適化されたビットマップが適用されていることがわかります。

good 2016 plan

そのビットマップにより、結合による行グループの削除が可能になります。

SQL Server 2014では、結合があり、MAXDOPが1である最後のクエリを除いて、クエリに対して同様のパフォーマンス結果が得られます。これは、実行に21秒かかります。クエリプランは次のとおりです。

bad query plan

ビットマップがなく、スキャンがバッチモードで実行されていません。 6700万行すべてをハッシュ結合に送り返します。

SQL Server 2014では、シリアルプランはバッチモードの対象ではありません。クエリが何らかの理由でシリアルで実行されている場合は、発生したパフォーマンスの低下を説明できます。 c = 100を直接フィルタリングするクエリも行モードで実行されますが、それでもすぐに終了することに注意してください。

2
Joe Obbish