SQL Server - секционированные таблицы против кластерного индекса? - PullRequest
15 голосов
/ 23 сентября 2008

Предположим, у вас есть одна массивная таблица с тремя столбцами, как показано ниже:

[id] INT NOT NULL,

[date] SMALLDATETIME NOT NULL,

[sales] FLOAT NULL

Также предположим, что вы ограничены одним физическим диском и одной файловой группой (ПЕРВИЧНАЯ). Вы ожидаете, что в этой таблице будут храниться более 10 000 000 идентификаторов на 100 дат (легко 1B + записи).

Как и во многих сценариях хранилищ данных, данные обычно растут последовательно по дате (т. Е. Каждый раз, когда вы выполняете загрузку данных, вы будете вставлять новые даты и, возможно, обновлять некоторые из более поздних дат данных). Для аналитических целей данные часто запрашиваются и агрегируются для случайного набора ~ 10000 идентификаторов, который будет указан через соединение с другой таблицей. Часто в этих запросах не указываются диапазоны дат и не задаются очень широкие диапазоны дат, что приводит меня к моему вопросу: каков наилучший способ индексации / разбиения этой таблицы?

Я думал об этом некоторое время, но застрял с противоречивыми решениями:

Опция # 1: Поскольку данные будут загружаться последовательно по дате, определите кластерный индекс (и первичный ключ) как [дата], [идентификатор]. Также создайте функцию / схему разделения «скользящего окна» на дату, позволяющую быстро перемещать новые данные в / из таблицы. Потенциально создайте некластеризованный индекс по идентификатору, чтобы помочь с запросами.

Ожидаемый результат № 1: Эта установка будет очень быстрой для целей загрузки данных, но неоптимальной, когда речь идет о аналитическом чтении, как, в худшем случае (без ограничения по датам, не повезло набор идентификаторов запрашивается), 100% страниц данных могут быть прочитаны.

Вариант № 2: Поскольку данные будут запрашиваться только для небольшого подмножества идентификаторов за один раз, определите кластерный индекс (и первичный ключ) как [id], [date]. Не беспокойтесь о создании секционированной таблицы.

Ожидаемый результат № 2: Ожидаемый огромный удар по производительности при загрузке данных, поскольку мы больше не можем быстро ограничивать по дате. Ожидаемый огромный выигрыш в производительности, когда речь заходит о моих аналитических запросах, так как это минимизирует количество прочитанных страниц данных.

Вариант № 3: Кластеризация (и первичный ключ) следующим образом: [id], [date]; функция / схема разбиения «скользящее окно» на дату.

Ожидаемый результат № 3: Не уверен, чего ожидать. Учитывая, что первый столбец в кластеризованном индексе - это [id] и, таким образом (насколько я понимаю), данные упорядочены по ID, я ожидаю хорошей производительности от моих аналитических запросов. Однако данные разбиты по дате, что противоречит определению кластеризованного индекса (но все равно выравнивается, поскольку дата является частью индекса). Я не нашел много документации, в которой говорилось бы об этом сценарии и о том, какие преимущества от производительности я могу получить от этого, что подводит меня к моему последнему бонусному вопросу:

Если я создаю таблицу в одной файловой группе на одном диске с кластеризованным индексом в одном столбце, есть ли какое-либо преимущество (кроме переключения разделов при загрузке данных), которое дает определение раздела в том же столбце?

Ответы [ 6 ]

7 голосов
/ 23 сентября 2008

Эта таблица очень узкая. Если реальная таблица будет такой узкой, вы должны быть счастливы, если будете выполнять сканирование таблицы вместо index-> ​​lookups.

Я бы сделал это:

CREATE TABLE Narrow
(
  [id] INT NOT NULL,
  [date] SMALLDATETIME NOT NULL,
  [sales] FLOAT NULL,
  PRIMARY KEY(id, date)  --EDIT, just noticed your id is not unique.
)

CREATE INDEX CoveringNarrow ON Narrow(date, id, sales)

Это обрабатывает точечные запросы с поиском и широкополосными запросами с ограниченным сканированием по критерию даты и идентификатору. Нет поиска для каждой записи из индекса. Да, я удвоил время записи (и использованное пространство), но это нормально, имхо.


Если есть какая-то потребность в конкретном фрагменте данных (а эта потребность демонстрируется профилированием !!), я бы создал кластеризованное представление, предназначенное для этого раздела таблицы.

CREATE VIEW Narrow200801
AS
SELECT * FROM Narrow WHERE '2008-01-01' <= [date] AND [date] < '2008-02-01'
--There is some command that I don't have at my finger tips to make this a clustered view.

Кластерные представления могут использоваться в запросах по имени, или оптимизатор выберет использование кластерных представлений, когда уместны предложения FROM и WHERE. Например, этот запрос будет использовать кластерное представление. Обратите внимание, что базовая таблица упоминается в запросе.

SELECT SUM(sales) FROM Narrow WHERE '2008-01-01' <= [date] AND [date] < '2008-02-01'

Поскольку index позволяет вам сделать определенные столбцы удобным для доступа ... Кластерное представление позволяет вам сделать определенные строки удобным для доступа.

3 голосов
/ 23 сентября 2008

Кластерный индекс даст вам преимущества в производительности для запросов при локализации ввода-вывода. Дата - это традиционная стратегия разбиения, так как многие D / W-запросы рассматривают движения по дате.

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

Было бы несколько необычно видеть значительное увеличение производительности от кластерного индекса при различной аналитической рабочей нагрузке. Оптимизатор запросов будет использовать метод под названием 'Пересечение индексов' , чтобы выбирать строки, даже не обращаясь к таблице фактов. См. Здесь для сообщения, которое я сделал на другой вопрос, который объясняет это более подробно с некоторыми ссылками. Кластерный индекс может или не может участвовать в пересечении индекса, поэтому вы можете обнаружить, что он сравнительно мало выигрывает от общей рабочей нагрузки запросов.

При загрузке вы можете столкнуться с обстоятельствами, когда кластерные индексы дают вам некоторую выгоду, особенно если вы получили производные вычисления (например, Заработанная премия ), которые вычисляются в процессе ETL. В этом случае вы можете получить некоторые преимущества. Если у вас есть определенный запрос, который, как вы знаете, будет выполняться постоянно, возможно, имеет смысл использовать для этого кластерные индексы. Опции # 2 и # 3 принесут вам значительную пользу только в том случае, если вы ожидаете, что этот тип запроса будет подавляющим большинством работы, выполняемой приложением.

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

0 голосов
/ 24 сентября 2008

Кластерный индекс в столбце даты не годится, если у вас будут вставки, которые будут вставлены быстрее, чем разрешение даты-времени, равное 3,33 мс. если вы это сделаете, вы получите 2 ключа с одинаковым значением, а ваш индекс должен будет получить еще один внутренний юниксификатор, который увеличит его размер.

Я бы пошел с # 2 из ваших вариантов.

0 голосов
/ 23 сентября 2008

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

0 голосов
/ 23 сентября 2008

Я бы сделал следующее:

  • Некластеризованный индекс на [Id]
  • Кластерный индекс на [Дата]
  • Преобразовать тип данных [sales] в числовое значение вместо числа с плавающей запятой
0 голосов
/ 23 сентября 2008

Если вы используете разделы в операторах выбора, то вы можете набрать некоторую скорость.

Если вы не используете его, а используете только «стандартные» варианты выбора, вы не получаете никакой выгоды.

По исходной проблеме: я бы порекомендовал вам вариант № 1 с включенным некластеризованным индексом по идентификатору.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...