Saya tidak tahan untuk tidak bergabung dengan Niko dengan jawaban lain (selamat datang, Niko!). Secara umum, saya setuju dengan Niko bahwa keterbatasan mode batch dalam SQL 2012 (jika Niko tidak akan terhubung ke blognya sendiri, saya akan :)) mungkin menjadi perhatian utama. Tetapi jika Anda bisa hidup dengan itu dan memiliki kontrol penuh atas setiap permintaan yang Anda tulis di meja untuk memeriksanya dengan cermat, kolom toko dapat bekerja untuk Anda di SQL 2012.
Sejauh pertanyaan spesifik Anda tentang kolom identitas, saya menemukan bahwa kolom identitas dikompresi dengan sangat baik dan akan sangat menyarankan untuk memasukkannya ke dalam indeks toko kolom Anda dalam setiap pengujian awal Anda. (Perhatikan bahwa jika kolom identitas juga merupakan indeks berkerumun dari b-tree Anda, itu akan secara otomatis dimasukkan ke dalam indeks penyimpanan kolom non-berkerumun Anda .)
Untuk referensi, berikut adalah ukuran yang saya amati untuk ~ 10MM baris data kolom identitas. The columnstore dimuat untuk kompres eliminasi segmen optimal hingga 26MB (vs 113MB untuk PAGE
kompresi tabel rowstore), dan bahkan kolomstore dibangun pada b-tree yang dipesan secara acak hanya 40MB. Jadi ini menunjukkan manfaat kompresi yang sangat besar, bahkan melebihi kompresi b-tree terbaik yang ditawarkan SQL dan bahkan jika Anda tidak repot-repot menyelaraskan data Anda untuk penghapusan segmen optimal (yang akan Anda lakukan dengan terlebih dahulu membuat b-tree dan kemudian membangun kolomstore Anda dengan MAXDOP
1).
Berikut ini skrip lengkap yang saya gunakan jika Anda ingin bermain-main:
-- 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