Мне нужно добавить вычисляемый постоянный столбец в большую таблицу (~ 1B строк).Могу ли я сделать это как-то в пакетном режиме или с помощью существующего предварительно рассчитанного столбца?
Сначала я попробовал просто с простым столбцом:
ALTER TABLE [dbo].[T] ADD [X] [decimal](32, 6) NULL
GO
UPDATE [dbo].[T]
SET [X] = [Y] / [Z]
Примерно через 14 часов это полностью заполнило 2 диска с журналом транзакций ине удалось.Так что я сделал это обновление в цикле в пакетах - все сделано в течение 7 часов и без блокировки для пользовательских запросов.
Теперь мне нужно, чтобы этот столбец автоматически поддерживался для новых записей - следовательно, с учетом сохраняемого вычисляемого столбца.Я хочу, чтобы время простоя таблицы было как можно меньше (в идеале - нет).Глядя на опыт работы с простым обновлением и пакетным обновлением, я хотел бы как-то сделать это в пакетном режиме или использовать существующий столбец (который содержит результат вычисления) - есть ли способ как этого добиться?
Мне нужен постоянный столбец, так как я должен индексировать его позже, а также потому, что я оптимизирую запрос, где вычисление скаляра (точного выражения, которое я собираюсь сохранить) занимает значительное количество времени.Я также рассматривал индексированное представление, но я обеспокоен тем, что может возникнуть та же проблема с долго выполняющейся транзакцией.
Sql Server 2016 (Enterprise).Простой режим восстановления.
РЕДАКТИРОВАТЬ: Для справки в будущем (и если кто-то найдет это полезным) - вот варианты, которые я рассмотрел (и протестировал):
ALTER TABLE [dbo].[T] ADD [X] AZ [Y] / [Z] PERSISTED
Плюсы: просто, обеспечена целостность
Минусы: одна транзакция - огромные требования к журналу транзакций и еслипровалился на полпути - весь прогресс потерян;невозможно выполнить онлайн - любые запросы к таблице заблокированы
Индексированное представление
CREATE VIEW [dbo]. [T_view] --indexedпросмотр со схемой, как SELECT [Y], [Z], [Y] / (NULLIF (Z, 0)) AS [Z] FROM [dbo]. [T] GO
- первый индекс материализованногопредставление должно быть уникальным и кластеризованным. CREATE UNIQUE CLUSTERED INDEX IDX_T_view
ON [dbo]. [T_view] ([Z]) GO
Плюсы: базовая таблица не фрагментируется придобавление столбцов
Минусы: в основном необходимость уникальности индекса.Плюс также одна транзакция
Непостоянный вычисляемый столбец с индексом:
ALTER TABLE [dbo]. [T] ADD [X]AZ [Y] / [Z]
СОЗДАТЬ НЕКЛАСТЕРНЫЙ ИНДЕКС [IX_T] ВКЛ [dbo]. [T] ([X] ASC)
Плюсы: Быстрый,нет фрагментации таблицы (поскольку физические изменения не выполняются)
Минусы: вычисляемый столбец по-прежнему необходимо вычислять каждый раз, когда он выбран.
- Триггер вставки / обновления:
Плюсы: мы можем сначала обновить данные в пакетном режиме, а затем сохранить базу данных, чтобы позаботиться об обновлении вновь вставленных строк.Столбец можно использовать в предложении WHERE фильтруемого индекса
Минусы: обеспечение целостности (у нас могут быть некоторые вставки / обновления в меню, когда мы обновляем таблицу партиями)
- Создание новой таблицы и итерационное перемещение данных:
Плюсы: То же, что и с триггером.Вычисляемый столбец, как правило, более производительный, чем триггер;Мы можем планировать перемещение данных таким образом, чтобы получить хорошо дефрагментированную таблицу
Минусы: так же, как с триггером.Кроме того, нам нужно дополнительное пространство.
EDIT2: После 2 дней перемещения индексов построения данных я обнаружил, что вычисляемый столбец (даже если он сохраняется) не может использоваться в предложении where фильтруемого индекса.Даже после того, как я переместил его из выражения фильтра во включающие столбцы (чтобы SQL все еще мог выполнять выборку только на основе этого индекса), производительность значительно снизилась.Так что мне нужно было конвертировать для вставки триггерного решения.