Стовпець ідентичності в індексі магазину стовпців


9

У мене надзвичайно велика таблиця IMO (~ 137 мільйонів рядків) з великою кількістю повторених даних, безліччю NULLстовпців тощо.

Я розглядаю це за допомогою таблиці з a COLUMNSTORE INDEXі у мене є IDENTITYстовпець у вихідній таблиці, який є моїм єдиним стовпцем, де кожен рядок є унікальним.

Чи слід залишити цей стовпець поза межі або включити його? Я читав, що ви хочете включити всі рядки своєї таблиці до, COLUMNSTORE INDEXале я також прочитав, що найкращими кандидатами є стовпці з великою кількістю неповторних рядків.

Це просто поганий кандидат на COLUMNSTORE INDEX?

Я використовую SQL Server 2012, тому це некластеризований стовпчик. Я просто вивчаю можливі кращі способи зберігання цих даних. Оновлення відсутні, хоча нові рядки періодично додаватимуться в процесі ELT, тому я припускаю, що там буде зроблено певну роботу. Деякі люди видобувають ці дані та створюють величезні звіти, багато сканування рядків, приводить сервер до сканування часом, що змушує нас щодня завантажувати копію на вторинний сервер.


1
Чи є стовпець ідентичності в оригінальній таблиці також вашим кластерним індексом? Якщо так, SQL Server автоматично включить цей стовпець у будь-який некластеризований індекс зберігання стовпців, навіть якщо ви прямо не вимагаєте цього. Це дещо схоже з тим, що кластеризовані стовпці індексів будуть включені до некластеризованого b-дерева індексу, але в цьому випадку дані будуть зберігатися як фактичні стислі сегменти стовпців. Див. Dba.stackexchange.com/questions/103722/… для отримання додаткової інформації.
Джефф Паттерсон

137 million rowsвеликий, але керований. Ви розглядали поділ таблиці та розміщення її на різних файлових групах? Індекс Columnstore в sql 2012 не піддається запису, тому ви зіткнетеся з проблемами - вам доведеться скинути і відтворити його. Я не кажу, що воля стовпчика є поганою, але краще вивчити й інші варіанти.
Кін Шах

Відповіді:


11

Стовпці ідентичності не по-справжньому стискаються в індексах Columnstore в SQL Server 2012 або в SQL Server 2014. Все це справді буде залежати від завантаженості роботи. Якщо ваше навантаження буде містити стовпчик ідентичності, ви можете дуже красиво скористатися вилученням сегмента.

З точки зору стиснення - Columnstore забезпечить вам кращу компресію, ніж зазвичай сторінка. Зазвичай. Будь ласка, протестуйте його перед тим, як перейти до виробництва.

Вашою найбільшою проблемою в SQL Server 2012 буде дуже слабка реалізація пакетного режиму, і ви нічого не можете з цим зробити.


7
Ласкаво просимо Ніко !!!
Аарон Бертран

3

Я не втримався приєднатися до Ніко з іншою відповіддю (ласкаво просимо, Ніко!). Загалом, я погоджуюсь з Niko, що обмеження режиму пакетного використання в SQL 2012 (якщо Ніко не посилатиметься на свій власний блог, я буду :)) може викликати серйозне занепокоєння. Але якщо ви можете жити з ними і мати повний контроль над кожним запитом, який ви пишете проти таблиці, щоб ретельно перевірити його, то стовпчик може працювати для вас у SQL 2012.

Що стосується ваших конкретних запитань щодо стовпця особи, я виявив, що стовпець ідентифікації стискається дуже добре, і настійно рекомендую включити його до вашого індексу зберігання стовпців при будь-якому початковому тестуванні. (Зверніть увагу, що якщо стовпець ідентичності буде також кластерним індексом вашого b-дерева, він буде автоматично включений у ваш некластеризований індекс магазину стовпців .)

Для довідки, ось розміри, які я спостерігав для ~ 10 ММ рядків даних стовпців ідентичності. Магазин стовпців, завантажений для оптимального усунення сегмента, стискається до 26 Мб (проти 113 МБ для PAGEстиснення таблиці рядків), і навіть стовпчик, побудований на випадково впорядкованому b-дереві, становить лише 40 МБ. Таким чином, це показує величезну перевагу стиснення навіть над найкращою компресією b-дерева, яку може запропонувати SQL, і навіть якщо ви не намагаєтеся вирівняти свої дані для оптимального усунення сегмента (що ви зробите, створивши спершу 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. Ми активізуємо оновлення, тому я сподіваюся, що в наступному році чи так ми зможемо це зробити.
Дон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.