web-dev-qa-db-fra.com

Comment créer une vue avec SNAPSHOT_MATERIALIZATION dans SQL Server 2017?

SQL Server 2017 a quelques nouvelles procédures stockées:

  • sp_refresh_single_snapshot_view - paramètre d'entrée pour @view_name nvarchar (261), @rgCode int
  • sp_refresh_snapshot_views - paramètre d'entrée pour @rgCode int

Et de nouvelles entrées dans sys.messages:

  • 10149 - Un index qui a SNAPSHOT_MATERIALIZATION ne peut pas être créé sur la vue ‘%. * Ls’ car la définition de la vue contient des tables optimisées en mémoire.
  • 10642 - SNAPSHOT_MATERIALIZATION ne peut pas être défini pour l'index "%. * Ls" sur "%. * Ls" car il ne s'applique qu'aux index des vues.
  • 10643 - SNAPSHOT_MATERIALIZATION ne peut pas être défini pour "%. * Ls" sur "%. * Ls" car il ne s'applique qu'aux index clusterisés sur les vues.
  • 10648 - SNAPSHOT_MATERIALIZATION ne peut pas être défini pour l'index partitionné '%. * Ls' sur '%. * Ls'.
  • 10649 - L’index non cluster ‘%. * Ls’ ne peut pas être créé sur ‘%. * Ls’ qui a groupé l’index ’%. * Ls’ avec SNAPSHOT_MATERIALIZATION.
  • 10650 - L'actualisation de la ou des vues d'instantané nécessite l'activation de l'isolement d'instantané sur la base de données.
  • 3760 - Impossible de supprimer l'index "%. * Ls" dans la vue "%. * Ls" qui a SNAPSHOT_MATERIALIZATION.
  • 4524 - Impossible de modifier la vue ‘%. * Ls’ car elle a une matérialisation de capture instantanée.
  • 4525 - Impossible d'utiliser le conseil "% ls" sur la vue "%. * Ls" qui a matérialisé un instantané avant que la vue ne soit actualisée.

Et de nouveaux événements étendus:

Snapshot view Extended Events

Alors, comment pouvons-nous créer une vue matérialisée par un instantané? (Microsoft ne l'a pas encore documenté, évidemment.) Voici un Gist avec des choses que j'ai essayées jusqu'à présent qui n'a pas fonctionné.

36
Brent Ozar

Tu ne peux pas. La fonctionnalité est désactivée dans 2017 RTM.


Cela dit, vous pouvez ...

Utilisation d'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);

Les modifications apportées aux tables sous-jacentes ne sont pas immédiatement reflétées dans la vue (comme c'est normalement le cas avec SQL Server). De même, les modifications de données par rapport aux tables sous-jacentes n'ont pas à maintenir la vue indexée de l'instantané.

Pour actualiser le contenu de la vue, il faut appeler l'une des nouvelles procédures stockées:

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

Cela produit le plan d'exécution:

Plan

Cela ne fonctionnera probablement pas pour vous, car soit un indicateur de trace non documenté est nécessaire, soit vous devez faire la chose particulièrement désagréable que j'ai faite: écrire à l'emplacement de mémoire contenant l'indicateur de fonctionnalité (à l'aide d'un débogueur) pour activer cette fonctionnalité.

Si vous êtes curieux, l'indicateur de fonctionnalité est l'octet à sqllang!g_featureSwitchesLangSvc+0x10f. Il est vérifié pendant sqllang!SpRefreshSingleSnapshotView.

Si vous voulez jouer le jeu et que vous êtes prêt à accepter les conséquences du piratage dans le code de SQL Server pendant son exécution et à utiliser une fonctionnalité que Microsoft ne pense pas encore prête:

  1. Attachez un débogueur au processus SQL Server 2017. J'utilise WinDbg.
  2. Définissez un point d'arrêt:

    bp sqllang!SpRefreshSingleSnapshotView
    
  3. Reprenez SQL Server à l'aide de la commande Go (g)

  4. Créez la vue ci-dessus, mais pas encore l'index cluster unique
  5. Exécutez le sys.sp_refresh_single_snapshot_view commande ci-dessus
  6. Lorsque le point d'arrêt est atteint, parcourez jusqu'à ce que vous voyiez la ligne de code:

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

    Le décalage peut être différent dans d'autres versions, par exemple en 2017 RTM CU3 c'est sqllang!g_featureSwitchesLangSvc+0x114

  7. L'adresse mémoire entre parenthèses peut être différente. Utilisez celui que vous voyez.

  8. Utilisez la commande d'affichage de la mémoire pour voir la valeur actuelle à l'adresse de mémoire que vous avez trouvée:

    db 00007fff`328dfbcf L1
    
  9. Cela devrait afficher un zéro, indiquant que la fonctionnalité est désactivée.

  10. Remplacez le zéro par un, en utilisant la commande enter values ​​(à nouveau avec votre adresse mémoire):

    eb 00007fff`328dfbcf 1
    
  11. Désactivez le point d'arrêt et reprenez l'exécution de SQL Server.

  12. La fonction est maintenant activée.
  13. Créez l'index cluster unique sur la vue.
  14. S'amuser.

Remarque SNAPSHOT_MATERIALIZATION nous permet de matérialiser un instantané d'une spécification de requête qui ne pouvait normalement pas être indexée, par exemple, le ci-dessous utilise 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);

Résultat:

Les commandes ont abouti.
56
Paul White 9