列ストアインデックスのID列


9

非常に大きなテーブルIMO(約1億3700万行)があり、繰り返しデータやNULL列がたくさんあります。

を含むテーブルを使用してこれを検討することを検討しCOLUMNSTORE INDEXていIDENTITYます。元のテーブルに列があります。これは、すべての行が一意である唯一の列です。

この列を省略するか、含める必要がありますか?テーブルのすべての行をに含めたいとCOLUMNSTORE INDEX読んだことがありますが、最適な候補は、一意でない行がたくさんある列であることも読みました。

これは単に悪い候補COLUMNSTORE INDEXですか?

SQL Server 2012を使用しているため、非クラスター化列ストアです。私はこのデータを格納するための可能なより良い方法を探っているところです。更新は存在しませんが、ELTプロセスによって新しい行が定期的に追加されるため、そこで作業が行われると想定しています。一部の人々はこのデータをマイニングして膨大なレポートを生成し、多くの行をスキャンして、サーバーをクロールさせて、コピーを毎日セカンダリサーバーにオフロードすることを余儀なくさせています。


1
元のテーブルのID列もクラスター化インデックスですか?その場合、明示的に要求しなくても、SQL Serverはその列を非クラスター化列ストアインデックスに自動的に含めます。これは、クラスター化インデックス列が非クラスター化bツリーインデックスに含まれる方法と多少似ていますが、この場合、データは実際の圧縮列ストアセグメントとして格納されます。詳細については、dba.stackexchange.com / questions / 103722 /…を参照してください。
Geoff Patterson

137 million rows大きいですが扱いやすいです。テーブルをパーティション分割して別のファイルグループに配置することを検討しましたか?SQL 2012のColumnsstoreインデックスは書き込み可能ではないため、問題が発生します-削除して再作成する必要があります。columnstoreが悪いとは言わないが、他のオプションも検討する方が良い。
Kin Shah

回答:


11

ID列は、SQL Server 2012またはSQL Server 2014の列ストアインデックスでは本当に圧縮されていません。すべて、実際に発生しているワークロードに依存します。ワークロードにID列が含まれる場合は、セグメントの削除を非常に美しく活用できます

圧縮の観点から-Columnstoreは、通常のページよりも優れた圧縮を提供します。通常。本番環境に進む前にテストしてください。

SQL Server 2012での最大の問題は、バッチモードの実装が非常に弱いことであり、それに対してあなたができることは何もありません。


7
ようこそニコ!
アーロンバートランド

3

私は別の答えでニコに加わることに抵抗することができませんでした(ようこそ、ニコ!)。一般に、SQL 2012のバッチモードの制限(Nikoが自分のブログにリンクしない場合、私は:)が主要な懸念事項である可能性があることをNikoに同意します。しかし、それらに対応し、テーブルに対して作成するすべてのクエリを完全に制御して慎重に検査できる場合、SQL 2012で列ストアが機能する可能性があります。

ID列に関する特定の質問に関する限り、ID列は圧縮率が非常に高いことがわかりました。初期テストでは、列ストアインデックスに含めることを強くお勧めします。(ID列がBツリーのクラスター化インデックスでもある場合は、非クラスター化列ストアインデックスに自動的に含まれます。)

参考までに、ID列データの約10 MM行で観察したサイズを以下に示します。最適なセグメントを削除するためにロードされた列ストアは26MB(PAGE行ストアテーブルの圧縮では113MB)に圧縮され、ランダムに並べられたbツリー上に構築された列ストアもわずか40MBです。したがって、これは、SQLが提供する必要のある最高のBツリー圧縮を超えて、最適なセグメントの削除のためにデータを調整する必要がない場合でも、最初にBツリーを作成してから、MAXDOP1で列ストアを構築します。

ここに画像の説明を入力してください

以下は、私が遊んでみたい場合に使用した完全なスクリプトです。

-- Confirm SQL version
SELECT @@version
--Microsoft SQL Server 2012 - 11.0.5613.0 (X64) 
--  May  4 2015 19:05:02 
--  Copyright (c) Microsoft Corporation
--  Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 9600: )


-- Create a columnstore table with identity column that is the primary key
-- This will yield 10 columnstore segments @ 1048576 rows each
SELECT i = IDENTITY(int, 1, 1), ROW_NUMBER() OVER (ORDER BY randGuid) as randCol
INTO #testIdentityCompression_sortedColumnstore
FROM (
    SELECT TOP 10485760 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS randI, NEWID() AS randGuid
    FROM master..spt_values v1
    CROSS JOIN master..spt_values v2
    CROSS JOIN master..spt_values v3
) r
ORDER BY r.randI
GO
ALTER TABLE #testIdentityCompression_sortedColumnstore
ADD PRIMARY KEY (i)
GO
-- Load using a pre-ordered b-tree and one thread for optimal segment elimination
-- See http://www.nikoport.com/2014/04/16/clustered-columnstore-indexes-part-29-data-loading-for-better-segment-elimination/
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_#testIdentityCompression_sortedColumnstore ON #testIdentityCompression_sortedColumnstore (i) WITH (MAXDOP = 1)
GO

-- Create another table with the same data, but randomly ordered
SELECT *
INTO #testIdentityCompression_randomOrderColumnstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_randomOrderColumnstore
ADD UNIQUE CLUSTERED (randCol)
GO
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_#testIdentityCompression_randomOrderColumnstore ON #testIdentityCompression_randomOrderColumnstore (i) WITH (MAXDOP = 1)
GO

-- Create a b-tree with the identity column data and no compression
-- Note that we copy over only the identity column since we'll be looking at the total size of the b-tree index
-- If anything, this gives an unfair "advantage" to the rowstore-page-compressed version since more
-- rows fit on a page and page compression rates should be better without the "randCol" column.
SELECT i
INTO #testIdentityCompression_uncompressedRowstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_uncompressedRowstore
ADD PRIMARY KEY (i)
GO

-- Create a b-tree with the identity column and page compression
SELECT i
INTO #testIdentityCompression_compressedRowstore
FROM #testIdentityCompression_sortedColumnstore
GO
ALTER TABLE #testIdentityCompression_compressedRowstore
ADD PRIMARY KEY (i)
WITH (DATA_COMPRESSION = PAGE)
GO

-- Compare all the sizes!
SELECT OBJECT_NAME(p.object_id, 2) AS tableName, COUNT(*) AS num_segments, SUM(on_disk_size / (1024.*1024.)) as size_mb
FROM tempdb.sys.partitions p
JOIN tempdb.sys.column_store_segments s
    ON s.partition_id = p.partition_id
    AND s.column_id = 1
WHERE p.object_id IN (OBJECT_ID('tempdb..#testIdentityCompression_sortedColumnstore'),OBJECT_ID('tempdb..#testIdentityCompression_randomOrderColumnstore'))
GROUP BY p.object_id
UNION ALL
SELECT OBJECT_NAME(p.object_id, 2) AS tableName
    , NULL AS num_segments
    , (a.total_pages*8.0) / (1024.0) as size_mb
FROM tempdb.sys.partitions p
JOIN tempdb.sys.allocation_units a
    ON a.container_id = p.partition_id
WHERE p.object_id IN (OBJECT_ID('tempdb..#testIdentityCompression_compressedRowstore'),OBJECT_ID('tempdb..#testIdentityCompression_uncompressedRowstore'))
ORDER BY 3 ASC
GO

すばらしい回答をありがとうございました。現在、少なくともsqlサーバー2014に接続できるようになるまで延期することを決定しました。アップグレードを強化しているので、来年かそれを実現できると期待しています。
Don
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.