Как ускорить массовое обновление кластеризованного столбца?

У меня довольно большая таблица: 20+ миллионов строк, и мне нужно обновить около 5% этого - или 1 миллион строк.

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

мой вопрос: Каков самый быстрый способ обновления этих строк?

Я попытался обновить строки напрямую:

update t1
set t1.groupId = t2.groupId
from
    table t1
join newtable t2 on t1.email = t2.email

но это занимает слишком много времени (я остановил его через 3 часа)

Я предполагаю, что это это потому, что вся строка (которая имеет 2 времени, 2 varchars и 2 ints) перемещается для каждого обновления.

а если я за первый кластерный индекс, тогда обновления, затем воссоздал кластерный индекс? Так будет быстрее?

Примечание: у меня есть некластеризованный индекс по электронной почте, если кто-то думает, что это медленная часть запроса. Это не так.

3 ответов


вот что я сделал (и это было намного быстрее):

  1. я уронил кластеризованный индекс.
  2. Я также уронил внешние ключи ссылки (два других int столбцы.)
  3. Я запустил инструкцию update
  4. я воссоздал индекс, который был быстрее, чем ожидалось. (Это первоначальная причина, по которой я спросил Так сначала).

этого довели весь процесс до нескольких секунд. Да, ~ 1 миллион строк примерно в 15 считанные секунды.

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

число физических чтений было утроено из-за этих поисков внешнего ключа.

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


в качестве примечания, я также попытался запустить обновление в пакетах:

update top(1000) t1
set t1.groupId = t2.groupId
from
    table t1
join newtable t2 on t1.email = t2.email

Это было хорошо (и, казалось, масштабировалось до 10K за партию), но все еще было порядка 1-2 минут каждой партии.


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


Я думаю, что комментарий ранее прав. Ты вроде как сам ответил на свой вопрос.

, потому что

кластеризованные индексы сортируют и хранят строки данных в таблице на основе их Ключевые значения (источник msdn),

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


Почему бы вам не сделать следующее:

  • сделайте другой столбец (один из varchar) кластеризованным индексом
  • создайте индекс на вашем groupId
  • обновление
  • затем обратный процесс.

Это должно быть быстрее.