Как создать представление с помощью SNAPSHOT_MATERIALIZATION в SQL Server 2017?

36

SQL Server 2017 имеет несколько новых хранимых процедур:

  • sp_refresh_single_snapshot_view - входной параметр для @view_name nvarchar (261), @rgCode int
  • sp_refresh_snapshot_views - параметр ввода для @rgCode int

И новые записи в sys.messages:

  • 10149 - Невозможно создать индекс с SNAPSHOT_MATERIALIZATION для представления "%. * Ls", так как определение представления содержит таблицы, оптимизированные для памяти.
  • 10642 - Невозможно задать SNAPSHOT_MATERIALIZATION для индекса "%. * Ls" для "%. * Ls", поскольку он применим только к индексам в представлениях.
  • 10643 - Невозможно установить SNAPSHOT_MATERIALIZATION для "%. * Ls" для "%. * Ls", поскольку оно применимо только к кластеризованным индексам в представлениях.
  • 10648 - Невозможно задать SNAPSHOT_MATERIALIZATION для многораздельного индекса "%. * Ls" для "%. * Ls".
  • 10649 - Невозможно создать некластеризованный индекс "%. * Ls" для "%. * Ls" с кластеризованным индексом "%. * Ls" с помощью SNAPSHOT_MATERIALIZATION.
  • 10650 - Обновление представлений снимков требует, чтобы в базе данных была включена изоляция снимков.
  • 3760 - Невозможно удалить индекс "%. * Ls" для представления "%. * Ls", имеющего SNAPSHOT_MATERIALIZATION.
  • 4524 - Невозможно изменить представление "%. * Ls", так как оно имеет материализацию снимков.
  • 4525 - Невозможно использовать подсказку "% ls" в представлении "%. * Ls", которое имеет материализацию моментальных снимков до обновления представления.

И новые расширенные события:

Просмотр снимка Расширенные события

Итак, как мы можем создать материализованное представление снимка? (Microsoft еще не документировала это, очевидно.) Вот суть того, что я пробовал до сих пор , но это не сработало.

Брент Озар
источник

Ответы:

55

Ты не можешь Функция отключена в 2017 RTM.


Тем не менее, вы можете ...

Использование AdventureWorks:

CREATE VIEW dbo.TH
WITH SCHEMABINDING
AS
SELECT P.ProductID, COUNT_BIG(*) AS cbs
FROM Production.Product AS P
JOIN Production.TransactionHistory AS TH
    ON TH.ProductID = P.ProductID
GROUP BY P.ProductID;
GO
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.TH (ProductID)
WITH (SNAPSHOT_MATERIALIZATION = ON);

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

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

EXECUTE sys.sp_refresh_single_snapshot_view
    @view_name = N'dbo.TH',
    @rgCode = 0; -- don't know what this is for yet

Это производит план выполнения:

План

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

Если вам интересно, флаг функции - это байт в sqllang!g_featureSwitchesLangSvc+0x10f. Проверено во время sqllang!SpRefreshSingleSnapshotView.

Если вы хотите подыграть и полностью готовы принять последствия взлома кода SQL Server во время его работы и использования функции, которую Microsoft пока не считает готовой:

  1. Присоедините отладчик к процессу SQL Server 2017. Я использую WinDbg.
  2. Установите точку останова:

    bp sqllang!SpRefreshSingleSnapshotView
  3. Возобновить SQL Server с помощью команды Go ( g)

  4. Создайте представление выше, но еще не уникальный кластеризованный индекс
  5. Запустите sys.sp_refresh_single_snapshot_viewкоманду выше
  6. Когда достигнута точка останова, проходите до тех пор, пока не увидите строку кода:

    cmp byte ptr [sqllang!g_featureSwitchesLangSvc+0x10f (00007fff`328dfbcf)],0

    Смещение может быть другим в других сборках, например в 2017 RTM CU3 оно sqllang!g_featureSwitchesLangSvc+0x114

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

  8. Используйте команду display memory, чтобы увидеть текущее значение по адресу памяти, который вы нашли:

    db 00007fff`328dfbcf L1
  9. Это должно показать ноль, указывая, что функция отключена.

  10. Измените ноль на единицу, используя команду ввода значений (снова с вашим адресом памяти):

    eb 00007fff`328dfbcf 1
  11. Отключите точку останова и возобновите работу SQL Server.

  12. Функция теперь включена.
  13. Создайте уникальный кластерный индекс в представлении.
  14. Тренировка

Примечание SNAPSHOT_MATERIALIZATIONпозволяет нам получить моментальный снимок спецификации запроса, который обычно не может быть проиндексирован, например, используется ниже MAX:

CREATE VIEW dbo.TH2
WITH SCHEMABINDING
AS
SELECT TH.ProductID, MaxTransactionID = MAX(TH.TransactionID)
FROM Production.TransactionHistory AS TH
GROUP BY TH.ProductID;
GO
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.TH2 (ProductID)
WITH (SNAPSHOT_MATERIALIZATION = ON);

Результат:

Команды выполнены успешно.
Пол Уайт говорит, что GoFundMonica
источник