web-dev-qa-db-ja.com

行の順序を維持しながらクラスター化列ストアインデックスを作成するコード

クラスター化列ストアインデックスを作成して、行ストアテーブルを列ストアテーブルに変換したいのですが。テーブルには、id、time、valueの3つの列があります。

列ストアインデックスを作成する前に、テーブルはIDと時間で並べ替えられます。ただし、列ストアインデックスを作成すると、行の順序がめちゃくちゃになります。並列処理が原因であると考え、maxdop = 1オプションを追加しましたが、問題は解決しませんでした。誰かがこれを手伝ってくれる?

以下は、テーブルとインデックスを作成するコードです。

-- creating rowstore table
drop table if exists tab1_rstore
select id, time, value
into tab1_rstore
from tab0
order by id_loan, period
option(maxdop 1)

-- creating clustered index on rowstore table
create clustered index idx on tab1_rstore (id,time)

-- creating columnstore table 
select * 
into tab1_cstore
from tab1_rstore
    option(maxdop 1)

-- comparing the first two rows from these two tables
    select top 2 *
from tab1_rstore

    select top 2 *
from tab1_cstore

クエリ結果のスクリーンショット:

Top two rows before c-index

-- creating clustered columnstore index
create clustered columnstore index idx on tab1_cstore 
with (maxdop = 1) 

-- comparing the top two rows again
select top 2 *
from tab1_rstore

select top 2 *
from tab1_cstore

列ストアインデックスを使用したクエリ結果のスクリーンショット:

enter image description here

私の理解では、行の順序は圧縮アルゴリズムによって決定され、それについて私たちができることは何もないということです。 document の制限と制限を以下の引用とともにここに示します。

インデックスのソートにASCまたはDESCキーワードを含めることはできません。列ストアインデックスは、圧縮アルゴリズムに従って順序付けられます。並べ替えを行うと、パフォーマンス上の利点の多くが失われます。

Windows 10 64ビットでSQL Server 2016 Developer Editionを使用しています。

8
Jason

クラスター化列ストアインデックスは、クラスター化行ストアインデックスとは根本的に異なります。クラスター化列ストアインデックスのキー列の指定がないことに気づいたかもしれません。そうです。クラスター化された列ストアインデックスは、キーのないインデックスです-すべての列が「含まれています」。

クラスター化された列ストアインデックスについて私が聞いた最も直感的な説明は、それを列指向のヒープテーブル( 'RID'は_rowgroup_id, row_number_)と考えることです。

直接の順序付けやポイント/小さい範囲の選択をサポートするためにインデックスが必要な場合は、SQL Server 2016のクラスター化された列ストアの上に更新可能な行ストアBツリーインデックスを作成できます。

列ストアアクセスとバッチモードの並べ替えは非常に高速であるため、多くの場合、これは単純に必要ではないです。行ストアのパフォーマンスについて人々が「知っている」ことの多くは、列ストアについて再学習する必要があります。スキャンとハッシュは良いです:)

つまり、列ストアはその行グループ(および各セグメントの最小値/最大値に関するメタデータ)に対する構造を持っているので、行グループ/セグメントの削除からメリットを得ることができるクエリで役立ちます。

この領域での1つの重要な手法は、最初に目的の順序でクラスター化された行ストアインデックスを作成し、次にWITH (DROP_EXISTING = ON, MAXDOP = 1)オプションを使用してクラスター化された列ストアインデックスを作成することです。あなたの例では:

_CREATE [UNIQUE] CLUSTERED INDEX idx 
ON dbo.tab1_cstore (id, time)
WITH (MAXDOP = 1);

CREATE CLUSTERED COLUMNSTORE INDEX idx 
ON dbo.tab1_cstore
WITH (DROP_EXISTING = ON, MAXDOP = 1);
_

行グループ/セグメントの削除の利点を長期にわたって維持するには、注意が必要です。また、列ストアは行グループによって既に暗黙的にパーティション化されていますが、明示的にパーティション化することもできます。

テストの対象が100%わからないが、セグメント内の値の「順序」は、圧縮アルゴリズム。 _DROP_EXISTING_を使用して列ストアインデックスを作成することについての私のポイントは、セグメント作成プロセスに流れ込むデータの順序付けであるため、セグメント全体は特定の方法で注文しました。セグメント内では、すべてのベットがオフになっています。

14
Paul White 9

余談ですが、SQL Server Tigerチームは、行グループを排除する機会を最大化するために、列ストアインデックスのビルドで_ORDER BY_句などが必要であることを認識していると思います。

また、現時点では、列ストアインデックスを構築するときに_MAXDOP = 1_を使用することを確認することが非常ここで 別の回答 のように重要です。そうしないと、データを複数のスレッドに分割して、最も効率的な行グループの排除の可能性を本質的に(おそらく劇的に)減少させます。

2
SQLArchitect