Что лучше для больших изменений в таблице: DELETE и INSERT каждый раз или UPDATE существующих?

27

Я делаю проект, в котором мне нужно ежедневно менять около 36 тысяч записей в одной таблице. Мне интересно, что будет работать лучше:

  1. удалить строки и вставить новые, или
  2. обновить уже существующие строки

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

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

Должен ли я удалить / вставить записи или обновить существующие (где это возможно) для этого ночного процесса?

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

Ответы:

9

Это действительно зависит от того, сколько данных меняется. Допустим, в этой таблице 20 столбцов. И у вас также есть 5 индексов - каждый на diff. колонка.

Теперь, если значения во всех 20 столбцах изменяются ИЛИ, даже если данные в 5 столбцах изменяются, и все эти 5 столбцов проиндексированы, тогда вам может быть лучше "удалить и вставить". Но если изменяются только 2 столбца и, допустим, они не являются частью каких-либо некластеризованных индексов, то вам может быть лучше «обновить» записи, потому что в этом случае будет обновляться только кластеризованный индекс (и индексам не придется обновляться).


В ходе дальнейших исследований я обнаружил, что приведенный выше комментарий является своего рода избыточным, поскольку внутри SQL Server имеется 2 отдельных механизма для выполнения ОБНОВЛЕНИЯ. - «Обновление на месте» (т. Е. Путем изменения значения столбца на новое в исходной строке) или как «ОБНОВЛЕНИЕ не на месте» (УДАЛЕНИЕ сопровождается ВСТАВКОЙ).

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

Например: если у вас есть кластеризованный индекс по фамилии, и у вас есть имена: Able, Baker, Charlie Теперь вы хотите обновить Baker до Becker. Никакие строки не должны быть перемещены. Так что это может занять место. Принимая во внимание, что если вам нужно обновить Able до Kumar, строки должны быть смещены (даже если они будут на одной странице). В этом случае SQL Server выполнит УДАЛЕНИЕ, а затем ВСТАВКУ.

Учитывая вышесказанное, я бы посоветовал вам сделать обычное ОБНОВЛЕНИЕ и позволить SQL Server выяснить, как это сделать внутренне.

Для получения более подробной информации о внутренних элементах «ОБНОВЛЕНИЕ» или о любых других внутренних элементах, связанных с SQL Server, обратитесь к Kalen Delaney, книге Пола Рэндала и др. - SQL Server 2008 Internals .

Дхармендар Кумар 'DK'
источник
8

Вы исследовали команду MERGE в SQL 2008? Вот основной пример:

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

Это в основном команда "UPSERT". Обновите, если он существует, вставьте его, если его нет. ОЧЕНЬ быстрая, очень классная команда.

datagod
источник
1
Это не быстрее, чем ОБНОВЛЕНИЕ, та же механика под капотом.
Марк Стори-Смит
Это быстрее обновления, чем вставка тех, которые еще не существовали.
Датагод
2
Если вы знаете, что это так, докажите это :)
Марк Стори-Смит
4

Но я сам проверил удаление и вставку vs Update в таблице с 30 миллионами записей. Эта таблица имеет один кластерный уникальный составной ключ и 3 некластеризованных ключа. Для удаления и вставки потребовалось 9 минут. На обновление ушло 55 мин. В каждой строке обновлен только один столбец.

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

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

Обновление не так быстро. Хитрость в том, чтобы добиться быстрой вставки - отключить индексы во время вставки данных.

Рассмотрите возможность использования этого:

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

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

UPDATE STATISTICS dbo.import_table

или

EXEC sp_updatestats

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

Asken
источник
4
Я не согласен, что это всегда так. Кроме того, TRUNCATE не может очистить таблицу в вопросе @ acceptilot, поскольку она содержит 89 млн записей, и он хочет обновить только 36 тыс. Записей.
Марк Стори-Смит
нужно научиться читать пост более внимательно! я обновлю пост ... на самом деле, мне нужно многое изменить.
Asken