Kolom identitas dalam indeks toko kolom

9

Saya memiliki tabel IMO yang sangat besar (~ 137 juta baris) dengan banyak data berulang, banyak NULLkolom, dan semacamnya.

Saya sedang mempertimbangkan menjelajahi ini menggunakan tabel dengan a COLUMNSTORE INDEXdan saya memiliki IDENTITYkolom di tabel asli, yang merupakan satu-satunya kolom saya di mana setiap baris unik.

Haruskah saya mengabaikan kolom ini atau memasukkannya? Saya telah membaca bahwa Anda ingin memasukkan semua baris tabel Anda ke dalam, COLUMNSTORE INDEXtetapi saya juga membaca bahwa kandidat terbaik adalah kolom dengan banyak baris yang tidak unik.

Apakah ini hanya kandidat yang buruk untuk COLUMNSTORE INDEX?

Saya menggunakan SQL Server 2012, jadi itu adalah toko kolom nonclustered. Saya hanya mengeksplorasi kemungkinan cara yang lebih baik untuk menyimpan data ini. Pembaruan tidak ada, meskipun baris baru akan ditambahkan secara berkala melalui proses ELT jadi saya mengasumsikan beberapa pekerjaan akan dilakukan di sana. Beberapa orang menambang data ini dan menghasilkan laporan besar, banyak pemindaian baris, membawa server ke perayapan pada waktu yang memaksa kami untuk memuat salinan setiap hari ke server sekunder.

Mengenakan
sumber
1
Apakah kolom identitas pada tabel asli juga indeks berkerumun Anda? Jika demikian, SQL Server akan secara otomatis memasukkan kolom itu dalam indeks columnstore non-clustered, bahkan jika Anda tidak secara eksplisit memintanya. Ini agak mirip dengan cara bahwa kolom indeks berkerumun akan dimasukkan dalam indeks b-tree yang tidak berkerumun, tetapi data akan disimpan sebagai segmen kolom kolom terkompresi yang sebenarnya dalam kasus ini. Lihat dba.stackexchange.com/questions/103722/... untuk info lebih lanjut.
Geoff Patterson
137 million rowsbesar tapi bisa diatur. Sudahkah Anda melihat ke partisi tabel dan meletakkannya di filegroup yang berbeda? Indeks Columnsstore di sql 2012 tidak dapat ditulisi, sehingga Anda akan mengalami masalah - Anda harus membuang dan membuatnya kembali. Saya tidak mengatakan kehendak kolomstore itu buruk, tetapi lebih baik untuk menjelajahi opsi lain juga.
Kin Shah

Jawaban:

11

Kolom identitas tidak benar-benar dikompresi dalam Indeks Kolom di SQL Server 2012 atau di SQL Server 2014. Itu semua akan benar-benar tergantung pada beban kerja yang Anda alami. Jika beban kerja Anda akan mencakup kolom identitas, maka Anda dapat memanfaatkan dengan sangat baik penghapusan Segmen.

Dari sudut pandang kompresi - Columnstore akan memberi Anda kompresi yang lebih baik daripada biasanya. Khas. Silakan mengujinya sebelum melanjutkan ke produksi.

Masalah terbesar Anda di SQL Server 2012 akan menjadi implementasi yang sangat lemah dari Mode Batch, dan tidak ada yang dapat Anda lakukan untuk itu.

Niko Neugebuer
sumber
7
Selamat datang Niko !!!
Aaron Bertrand
3

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 PAGEkompresi 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 MAXDOP1).

masukkan deskripsi gambar di sini

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
Geoff Patterson
sumber
Terima kasih atas semua jawaban yang bagus, saat ini saya telah memutuskan untuk menunda sampai saya bisa mendapatkan setidaknya sql server 2014. kami sedang meningkatkan upgrade kami jadi saya berharap di tahun depan atau lebih kita bisa melakukan ini.
Don