Добавление вычисляемого постоянного столбца в большую таблицу - PullRequest
0 голосов
/ 26 сентября 2018

Мне нужно добавить вычисляемый постоянный столбец в большую таблицу (~ 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 все еще мог выполнять выборку только на основе этого индекса), производительность значительно снизилась.Так что мне нужно было конвертировать для вставки триггерного решения.

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

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

0 голосов
/ 26 сентября 2018

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

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

  • Требования к владельцу
  • Требования к детерминизму
  • Требования к точности
  • Требования к типу данных
  • Требования к опции SET

https://docs.microsoft.com/en-us/sql/relational-databases/indexes/indexes-on-computed-columns?view=sql-server-2017

...