Performance tuning with result set caching (Настройка производительности с помощью упорядоченного кластеризованного индекса columnstore)

Область применения: выделенные пулы SQL Azure Synapse Analytics, SQL Server 2022 (16.x) и более поздних версий

Когда пользователи запрашивают таблицу columnstore в выделенном пуле SQL, оптимизатор проверяет минимальное и максимальное значения, хранящиеся в каждом сегменте. Сегменты, находящиеся вне границ предиката запроса, не считываются с диска в память. Запрос может быть выполнен быстрее, если количество сегментов для чтения и их общий размер невелики.

Сравнение упорядоченного кластеризованного индекса columnstore с неупорядоченным

По умолчанию для каждой таблицы, созданной без параметра индекса, внутренний компонент (построитель индексов) создает на нем неупорядоченный кластеризованный индекс columnstore (CCI). Данные в каждом столбце сжимаются в отдельный сегмент CCI rowgroup. Существуют метаданные для диапазона значений каждого сегмента, поэтому сегменты, находящиеся вне границ предиката запроса, не считываются с диска во время выполнения запроса. CCI обеспечивает наивысший уровень сжатия данных и уменьшает размер сегментов для чтения, чтобы запросы могли выполняться быстрее. Однако поскольку построитель индексов не сортирует данные перед их сжатием в сегменты, могут возникать сегменты с перекрывающимися диапазонами значений. Это приводит к тому, что запросы считывают больше сегментов с диска и на завершение процесса уходит больше времени.

Упорядоченные кластеризованные индексы columnstore за счет эффективного устранения сегментов, что значительно ускоряет производительность за счет пропуска больших объемов упорядоченных данных, которые не соответствуют предикату запроса. При создании упорядоченного CCI механизм пула SQL сортирует существующие данные в памяти по ключам порядка, прежде чем построитель индексов сжимает их в сегменты индекса. При использовании отсортированных данных перекрытие сегментов сокращается, позволяя запросам использовать более эффективное исключение сегментов и, следовательно, более высокую производительность, поскольку количество сегментов для чтения с диска меньше. Перекрытие сегментов можно избежать, если все данные могут быть отсортированы в памяти одновременно. В связи с большими таблицами в хранилищах данных этот сценарий происходит редко.

Чтобы проверить диапазоны сегментов для столбца, выполните следующую команду с именами ваших таблицы и столбца:

SELECT o.name, pnp.index_id,
cls.row_count, pnp.data_compression_desc,
pnp.pdw_node_id, pnp.distribution_id, cls.segment_id,
cls.column_id,
cls.min_data_id, cls.max_data_id,
cls.max_data_id-cls.min_data_id as difference
FROM sys.pdw_nodes_partitions AS pnp
   JOIN sys.pdw_nodes_tables AS Ntables ON pnp.object_id = NTables.object_id AND pnp.pdw_node_id = NTables.pdw_node_id
   JOIN sys.pdw_table_mappings AS Tmap  ON NTables.name = TMap.physical_name AND substring(TMap.physical_name,40, 10) = pnp.distribution_id
   JOIN sys.objects AS o ON TMap.object_id = o.object_id
   JOIN sys.pdw_nodes_column_store_segments AS cls ON pnp.partition_id = cls.partition_id AND pnp.distribution_id  = cls.distribution_id
JOIN sys.columns as cols ON o.object_id = cols.object_id AND cls.column_id = cols.column_id
WHERE o.name = '<Table Name>' and cols.name = '<Column Name>'  and TMap.physical_name  not like '%HdTable%'
ORDER BY o.name, pnp.distribution_id, cls.min_data_id;

Примечание

В упорядоченной таблице CCI новые данные, полученные в результате выполнения операций загрузки одного и того же пакета DML или данных, сортируются в пределах этого пакета, поэтому в таблице не существует глобальной сортировки по всем данным. Пользователи могут выполнить REBUILD для упорядоченного CCI, чтобы отсортировать все данные в таблице. В выделенном пуле SQL индекс columnstore REBUILD является автономной операцией. Для секционированной таблицы REBUILD выполняется по одной секции за раз. Данные в перестроенной секции находятся в автономном режиме и недоступны до завершения выполнения REBUILD для этого раздела.

Производительность запросов

Увеличение производительности запроса от упорядоченного CCI зависит от шаблонов запросов, размера данных, качества сортировки данных, физической структуры сегментов, а также класса DWU и ресурсов, выбранных для выполнения запроса. Прежде чем выбирать столбцы для упорядочивания при проектировании упорядоченной таблицы CCI, пользователям следует ознакомиться со всеми этими факторами.

Запросы со всеми этими шаблонами обычно выполняются быстрее с упорядоченным CCI.

  1. Запросы имеют предикаты равенства, неравенства или диапазона
  2. Столбцы предиката и упорядоченные столбцы CCI одинаковы.

В этом примере в таблице T1 имеется кластеризованный индекс columnstore, упорядоченный в последовательности Col_C, Col_B и Col_A.

CREATE CLUSTERED COLUMNSTORE INDEX MyOrderedCCI ON  T1
ORDER (Col_C, Col_B, Col_A);

Производительность запросов 1 и 2 может повысить эффективность упорядоченных CCI, чем другие запросы, так как они ссылаются на все упорядоченные столбцы CCI.

-- Query #1:

SELECT * FROM T1 WHERE Col_C = 'c' AND Col_B = 'b' AND Col_A = 'a';

-- Query #2

SELECT * FROM T1 WHERE Col_B = 'b' AND Col_C = 'c' AND Col_A = 'a';

-- Query #3
SELECT * FROM T1 WHERE Col_B = 'b' AND Col_A = 'a';

-- Query #4
SELECT * FROM T1 WHERE Col_A = 'a' AND Col_C = 'c';

Производительность загрузки данных

Производительность загрузки данных в упорядоченную таблицу CCI аналогична секционированной таблице. Загрузка данных в упорядоченную таблицу CCI может занять больше времени, чем в неупорядоченную таблицу CCI, из-за операции сортировки данных, однако запросы могут выполняться быстрее с упорядоченным CCI.

Ниже приведен пример сравнения производительности загрузки данных в таблицы с разными схемами.

Столбчатая диаграмма, на которой приведен пример сравнения производительности при загрузке данных в таблицы с разными схемами.

Ниже приведен пример сравнения производительности запросов между CCI и упорядоченным CCI.

Линейчатая диаграмма, сравнивающая производительность во время data_loading. Упорядоченный кластеризованный индекс columnstore имеет меньшую длительность.

Уменьшение перекрытия сегментов

Число перекрывающихся сегментов зависит от размера данных для сортировки, объема доступной памяти и параметра максимальной степени параллелизма (MAXDOP) во время создания упорядоченного CCI. Следующие стратегии сокращают перекрытие сегментов при создании упорядоченной CCI.

  • Используйте класс ресурсов xlargerc в более высоком классе DWU, чтобы обеспечить больше памяти для сортировки данных перед тем, как построитель индексов будет сжимать данные в сегменты. В сегменте индекса невозможно изменить физическое расположение данных. Сортировка данных внутри сегмента или между сегментами отсутствует.

  • Создайте упорядоченный CCI с OPTION (MAXDOP = 1). Каждый поток, используемый для создания упорядоченного CCI, работает с подмножеством данных и сортирует их локально. Глобальная сортировка данных, отсортированных различными потоками, отсутствует. Использование параллельных потоков позволяет сократить время создания упорядоченного CCI, но при этом будет создано больше пересекающихся сегментов, чем при использовании одного потока. Использование однопоточной операции обеспечивает наивысшее качество сжатия. Пример:

CREATE TABLE Table1 WITH (DISTRIBUTION = HASH(c1), CLUSTERED COLUMNSTORE INDEX ORDER(c1) )
AS SELECT * FROM ExampleTable
OPTION (MAXDOP 1);

Примечание

В настоящее время в выделенных пулах SQL в Azure Synapse Analytics параметр MAXDOP поддерживается только при создании упорядоченной таблицы CCI с помощью CREATE TABLE AS SELECT команды . Создание упорядоченной CCI с помощью CREATE INDEX команд или CREATE TABLE не поддерживает параметр MAXDOP. Это ограничение не распространяется на SQL Server 2022 и более поздних версий, где можно указать MAXDOP с CREATE INDEX помощью команд или CREATE TABLE .

  • Предварительная сортировка данных по ключам сортировки перед их загрузкой в таблицы.

Ниже приведен пример упорядоченного распределения таблицы CCI с нулевым перекрывающимся сегментом в соответствии с приведенными выше рекомендациями. Упорядоченная таблица CCI создается в базе данных DWU1000c с помощью CTAS из таблицы кучи размером 20 ГБ с помощью MAXDOP 1 и xlargerc. CCI упорядочивается по столбцу BIGINT без повторяющихся значений.

Снимок экрана: текстовые данные без перекрытия сегментов.

Создание упорядоченного CCI в больших таблицах

Создание упорядоченного CCI является автономной операцией. Для таблиц без секций данные не будут доступны пользователям до тех пор, пока не завершится процесс создания упорядоченного CCI. Для секционированных таблиц пользователи могут по-прежнему обращаться к данным в секциях, где не выполняется создание упорядоченного CCI, поскольку подсистема создает упорядоченный CCI по секциям. С помощью этого параметра можно сократить время простоя при создании упорядоченного CCI в больших таблицах:

  1. Создайте секции в целевой большой таблице (с именем Table_A).
  2. Создайте пустую упорядоченную таблицу CCI (с именем Table_B) с той же таблицей и схемой секционирования, что и в Table_A.
  3. Переместите одну секцию из Table_A в Table_B.
  4. Выполните ALTER INDEX <Ordered_CCI_Index> ON <Table_B> REBUILD PARTITION = <Partition_ID>, чтобы перестроить подключенную секцию в Table_B.
  5. Повторите шаги 3 и 4 для каждой секции в Table_A.
  6. После переключения всех секций с Table_A на Table_B и их перестроения удалите Table_A и переименуйте Table_B в Table_A.

Совет

Для таблицы выделенного пула SQL с упорядоченным кластеризованным индексом команда ALTER INDEX REBUILD будет выполнять повторную сортировку данных с помощью tempdb. Отслеживайте базу данных tempdb во время операций перестроения. Если вам необходимо больше места в базе данных tempdb, можно увеличить размер пула. Масштаб можно вернуть обратно после перестроения индекса.

Для таблицы выделенного пула SQL с упорядоченным кластеризованным индексом команда ALTER INDEX REORGANIZE не выполняет повторную сортировку данных. Для повторной сортировки используйте инструкцию ALTER INDEX REBUILD.

Дополнительные сведения об обслуживании хранилищ с упорядоченным кластеризованным индексом см. в разделе Оптимизация кластеризованных индексов columnstore.

Отличия возможностей SQL Server 2022

В выпуске SQL Server 2022 (16.x) появились упорядоченные кластеризованные индексы columnstore, аналогичные соответствующей возможности выделенных пулов SQL Azure Synapse.

  • В настоящее время только SQL Server 2022 (16.x) и более поздних версиях поддерживают расширенные возможности исключения кластеризованных столбцов columnstore для строковых, двоичных типов данных и guid, а тип данных datetimeoffset — для масштабирования больше двух. Ранее это исключение сегмента применялось к числовым типам данных, типам данных даты и времени, а также к типу данных datetimeoffset с масштабом меньше или равным двум.
  • В настоящее время только SQL Server 2022 (16.x) и более поздних версиях поддерживают исключение кластеризованной LIKE группы строк columnstore для префикса предикатов, например column LIKE 'string%'. Исключение сегмента не поддерживается для использования like без префикса, например column LIKE '%string'.

Дополнительные сведения см. в разделе Новые возможности индексов Columnstore.

Примеры

A. Чтобы проверить упорядоченные столбцы и порядковый номер упорядочивания:

SELECT object_name(c.object_id) table_name, c.name column_name, i.column_store_order_ordinal
FROM sys.index_columns i
JOIN sys.columns c ON i.object_id = c.object_id AND c.column_id = i.column_id
WHERE column_store_order_ordinal <>0;

Б. Чтобы изменить порядковый номер столбца, добавить или удалить столбцы из списка упорядочивания либо изменить CCI на упорядоченный CCI:

CREATE CLUSTERED COLUMNSTORE INDEX InternetSales ON dbo.InternetSales
ORDER (ProductKey, SalesAmount)
WITH (DROP_EXISTING = ON);

Дальнейшие действия