Повторная индексация большой таблицы - как я облажался?

У меня есть таблица размером 1 ТБ, 600 м, в которой есть ошибочный выбор индексированных столбцов, в частности кластеризованный индекс в столбце первичного ключа, который никогда не используется в запросе выбора.

Я хочу удалить кластерный индекс из этой строки и создать его для ряда других строк.

Таблица на данный момент такая:

  • colA (PK, nvarchar (3)) [кластеризованный индекс pt b]

  • colB (PK, bigint) [кластерный индекс pt a]

  • colC (DateTime) [некластеризованный индекс]

  • colD (Деньги) [некластеризованный индекс]

  • colE (бит) [без индекса]

  • colF (бит) [без индекса]

  • colG (int) [без индекса]

  • больше неиндексированных столбцов

Я бы хотел изменить его так:

  • colA (PK, nvarchar (3)) [кластерный индекс pt a]

  • colB (PK, bigint) [некластеризованный индекс]

  • colC (DateTime) [некластеризованный индекс]

  • colD (Деньги) [кластерный индекс pt d]

  • colE (бит) [кластерный индекс pt b]

  • colF (бит) [кластерный индекс pt c]

  • colG (int) [кластерный индекс pt e]

  • больше неиндексированных столбцов

Два вопроса: 1) Сколько времени, по вашему мнению, займет это изменение (спецификация сервера в конце сообщения). К сожалению, это живая БД, и у меня не может быть простоя, если я не знаю, как долго она будет работать.

2) Неужели добавление такого количества столбцов в кластерный индекс - ужасная идея? Обновления почти не выполняются. Есть много вставок и много выборок, которые всегда используют все предложенные индексированные строки в качестве параметров выбора.

Спецификация сервера: 5 дисков по 15 тыс. Об / мин в RAID 5, MS-SQL Sever 2005 и некоторые биты для их работы.


person Mr. Flibble    schedule 27.03.2009    source источник


Ответы (8)


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

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

  • уникальный
  • стабильный
  • как можно более узкий

Вы можете изменить свои некластеризованные индексы - без проблем. Но старайтесь не запутывать кластерный индекс! Это определенно снизит вашу производительность!

Ознакомьтесь с отличными статьями в блоге Кимберли Трипп об индексировании:

Марк

person marc_s    schedule 27.03.2009
comment
Это не всегда правда. Если таблица является тяжелой при чтении (а это и есть), чем более широкий кластеризованный индекс, особенно в полях, которые используются для аргументов поиска, фактически повысит производительность запроса в соответствии с целью предложенного им нового кластерного индекса). - person James; 27.03.2009
comment
Возможно, но одна вещь, которую многие люди не учитывают: весь кластеризованный ключ также будет частью любого некластеризованного ключа (все конечные узлы некластеризованного индекса) и, таким образом, может привести к раздуванию необходимого пространства. - person marc_s; 27.03.2009
comment
Эти статьи Кимберли великолепны. Спасибо. Кажется, что в индексировании так много сложностей, что мне действительно нужно опубликовать полную спецификацию моей проблемы, чтобы получить твердый ответ. Я постараюсь сделать это на выходных и повторно отправлю. - person Mr. Flibble; 27.03.2009
comment
Да, действительно - индексация намного сложнее и сложнее, чем может показаться на первый взгляд :-) - person marc_s; 28.03.2009

Я внес изменения, и это не заняло много времени. Вот время для каждой операции: первый раз при запуске на сервере резервного копирования с одним диском 7200 об / мин, а второй - на основном сервере с 15 КБ дисков в RAID.

ALTER TABLE Table DROP CONSTRAINT [PK_Table]

2:39 часов / 19 минут

CREATE CLUSTERED INDEX [IX_Clustered] ON [Table] 
(
 [a] ASC,
 [b] ASC,
 [c] ASC,
 [d] ASC,
 [e] ASC,
 [f] ASC
)WITH (PAD_INDEX  = ON, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 90, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = OFF) ON [PRIMARY]

15:30 / 2 часа

ALTER TABLE Table ADD CONSTRAINT
PK_hands PRIMARY KEY NONCLUSTERED 
(
 e,
 h
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

4 часа / 1 час

Наиболее часто используемый запрос select сейчас занимает ‹10 секунд, тогда как раньше это занимало от 10 до 15 минут. Хорошее улучшение! Время вставки тоже кажется немного быстрее.

person Mr. Flibble    schedule 05.04.2009

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

person Brian Ensink    schedule 27.03.2009
comment
Конечно, было бы здорово иметь это. Я ищу ответы на сумму менее 7000 долларов прямо сейчас, но, возможно, в будущем мне придется согласиться с вашим предложением. - person Mr. Flibble; 27.03.2009

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

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

person BradC    schedule 27.03.2009
comment
Если это не SQL 2005 Enterprise Edition (о котором он не говорит), создание нового индекса является автономной операцией. - person mrdenny; 31.03.2009

Возможно, вам не нужно беспокоиться о простоях, так как это может быть возможно внести изменения в реальном времени (без любого простоя). Применимо к выпуску SQL Server 2005 Enterprise.

person MarkusQ    schedule 27.03.2009

Одна вещь, которую вы могли бы сделать, если у вас есть дисковое пространство, - это создать вторую таблицу с правильным кластеризованным индексом, скопировать строки в новую таблицу в течение нескольких дней с помощью инкрементного процесса. Как только все строки будут там, выполните процедуру sp_rename для обеих таблиц (для этого потребуется всего несколько минут простоя. Если бы ваши приложения ссылались на представление, а не на физическую таблицу, вы могли бы сделать это с нулевым временем простоя для ваших приложений. Надеюсь, это поможет .

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

person James    schedule 27.03.2009

1) Сколько времени, по вашему мнению, займет это изменение (спецификация сервера в конце сообщения). К сожалению, это действующая БД, и у меня не может быть простоя, если я не знаю, как долго она будет простаивать.

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

2) Неужели добавлять так много столбцов в кластерный индекс - ужасная идея? Обновления почти не выполняются. Есть много вставок и много выборок, которые всегда используют все предложенные индексированные строки в качестве параметров выбора.

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

-Адам

person Adam Davis    schedule 27.03.2009

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

person Nathan Koop    schedule 27.03.2009