2008-09-23 2 views
15

Давайте предположим, что у вас есть один массивный стол с тремя колоннами, как показано ниже:SQL Server - Разделенные таблицы и кластерный индекс?

[id] INT NOT NULL, 

[date] SMALLDATETIME NOT NULL, 

[sales] FLOAT NULL 

предположить Также вы ограничены одного физического диска и одной файловой группы (PRIMARY). Вы ожидаете, что эта таблица будет продавать 10 000 000+ идентификаторов за 100 лет (легко 1Б + записи).

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

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

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

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

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

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

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

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

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

ответ

0

Если вы используете разделы в операциях select, то вы cn получаете некоторую скорость.

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

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

3

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

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

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

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

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

0

Я хотел бы сделать следующее:.

  • некластеризованного индекс на [ Id]
  • Кластерный указатель по [Дате]
  • Преобразовать [продажи] тип данных числовой, вместо поплавка
+0

Ваш последний пункт интересен. Какую выгоду вы ожидаете от конвертации в числовые из float? – 2008-09-23 13:42:40

+1

Вы можете быть более точным относительно данных, которые вы храните, а числовой тип данных - это точный номер, где поплавок является приблизительным числом. – GateKiller 2008-09-23 18:04:46

7

Эта таблица грозно узок. Если реальная таблица будет такой узкой, вы должны быть счастливы иметь сканирование таблицы вместо 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) 

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


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

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' 

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

0

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

0

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

Я бы выбрал 2 варианта.

Смежные вопросы