Столбец идентичности в индексе columnstore

9

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

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

Должен ли я оставить этот столбец или включить его? Я прочитал, что вы хотите включить все строки вашей таблицы в, COLUMNSTORE INDEXно я также прочитал, что лучшими кандидатами являются столбцы с большим количеством неуникальных строк.

Это просто плохой кандидат на COLUMNSTORE INDEX?

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

дон
источник
1
Является ли столбец идентификаторов в исходной таблице также вашим кластерным индексом? Если это так, SQL Server автоматически включит этот столбец в любой некластеризованный индекс columnstore, даже если вы явно не запрашиваете его. Это несколько похоже на то, как столбцы кластеризованного индекса будут включены в некластеризованный индекс b-дерева, но в этом случае данные будут храниться как фактические сжатые сегменты столбца. См. Dba.stackexchange.com/questions/103722/… для получения дополнительной информации.
Джефф Паттерсон
137 million rowsэто большой, но управляемый. Вы смотрели на разделение таблицы и размещение ее в разных файловых группах? Индекс ColumnStore в sql 2012 недоступен для записи, поэтому вы столкнетесь с проблемами - вам придется удалить его и создать заново. Я не говорю, что columnstore будет плохо, но лучше изучить и другие варианты.
Кин Шах

Ответы:

11

Столбцы идентификаторов действительно не сжимаются в индексах Columnstore в SQL Server 2012 или в SQL Server 2014. Все это будет действительно зависеть от рабочей нагрузки, с которой вы сталкиваетесь. Если ваша рабочая нагрузка будет включать в себя столбец идентификаторов, то вы сможете очень красиво использовать исключение сегментов.

С точки зрения сжатия - Columnstore предоставит вам лучшее сжатие, чем обычно делает страница. Как правило. Пожалуйста, проверьте это, прежде чем перейти к производству.

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

Нико Нойгебер
источник
7
Добро пожаловать Нико !!!
Аарон Бертран
3

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

Что касается ваших конкретных вопросов о столбце идентификаторов, я обнаружил, что столбец идентификаторов очень хорошо сжимается, и настоятельно рекомендую включить его в индекс вашего columnstore при любом начальном тестировании. (Обратите внимание, что если столбец идентификаторов также является кластерным индексом вашего b-дерева, он будет автоматически включен в ваш некластеризованный индекс columnstore .)

Для справки, вот размеры, которые я наблюдал для ~ 10MM строк данных столбца идентичности. Склад столбцов, загруженный для оптимального удаления сегментов, сжимается до 26 МБ (по сравнению со 113 МБ для PAGEсжатия таблицы хранилища строк), и даже хранилище столбцов, построенное из случайно упорядоченного b-дерева, составляет всего 40 МБ. Таким образом, это демонстрирует огромное преимущество сжатия, даже по сравнению с лучшим сжатием по b-дереву, которое может предложить SQL, и даже если вы не пытаетесь выровнять свои данные для оптимального удаления сегментов (что вы должны сделать, сначала создав b-дерево, а затем построение вашего columnstore с 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 server 2014. Мы активизируем наши обновления, поэтому я надеюсь, что в следующем году или около того мы сможем это сделать.
Дон