Nous avons un entrepôt de données avec un nombre d'enregistrements assez important (10-20 millions de lignes) et exécutons souvent des requêtes qui comptent les enregistrements entre certaines dates, ou comptons les enregistrements avec certains indicateurs, par exemple.
SELECT
f.IsFoo,
COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo
Les performances ne sont pas terribles, mais peuvent être relativement lentes (peut-être 10 secondes sur un cache froid).
Récemment, j'ai découvert que je pouvais utiliser GROUP BY
dans les vues indexées et a donc essayé quelque chose de similaire au suivant
CREATE VIEW TestView
WITH SCHEMABINDING
AS
SELECT
Date,
FlagId,
COUNT_BIG(*) AS WidgetCount
FROM Widgets
GROUP BY Date, FlagId;
GO
CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
Date,
FlagId
);
Par conséquent, les performances de ma première requête sont désormais <100 ms, et la vue et l'index résultants sont <100 Ko (bien que notre nombre de lignes soit élevé, la plage de dates et d'ID d'indicateur signifie que cette vue ne contient que 1000 à 2000 lignes).
Je pensais que cela réduirait peut-être les performances des écritures dans la table Widget, mais non - les performances des insertions et des mises à jour dans cette table sont à peu près inchangées pour autant que je sache (en plus, étant un entrepôt de données, cette table est mise à jour rarement. en tous cas)
Pour moi, cela semble trop beau pour être vrai - n'est-ce pas? À quoi dois-je faire attention lorsque j'utilise des vues indexées de cette manière?
Comme vous l'avez noté, la vue elle-même ne matérialise qu'un petit nombre de lignes - donc même si vous mettez à jour la table entière, les E/S supplémentaires impliquées dans la mise à jour de la vue sont négligeables. Vous avez probablement déjà ressenti la plus grande douleur que vous ressentirez lorsque vous aurez créé la vue. Le prochain plus proche sera si vous ajoutez un gazillion de lignes à la table de base avec un tas de nouveaux ID qui nécessitent de nouvelles lignes dans la vue.
Ce n'est pas trop beau pour être vrai. Vous utilisez les vues indexées exactement comme elles devaient être utilisées - ou au moins l'un des moyens les plus efficaces: payer pour les futures agrégations de requêtes au moment de l'écriture. Cela fonctionne mieux lorsque le résultat est beaucoup plus petit que la source et bien sûr lorsque les agrégations sont demandées plus souvent que les données sous-jacentes sont mises à jour (plus courantes dans DW qu'OLTP, en général).
Malheureusement, beaucoup de gens pensent que l'indexation d'une vue est magique - un index ne rendra pas toutes les vues plus efficaces, en particulier les vues qui joignent simplement des tables et/ou produisent le même nombre de lignes que la source (ou même se multiplient). Dans ces cas, les E/S de la vue sont identiques ou même pires que la requête d'origine, non seulement parce qu'il y a la même ou plusieurs lignes, mais souvent elles stockent et matérialisent également plus de colonnes. Ainsi, la matérialisation de ceux-ci à l'avance n'apporte aucun gain, car - même avec les SSD - les E/S, le réseau et le traitement/rendu client restent les principaux goulots d'étranglement dans le retour de grands ensembles de résultats au client. Les économies que vous obtenez en évitant la jointure lors de l'exécution ne sont tout simplement pas mesurables par rapport à toutes les autres ressources que vous utilisez toujours.
Comme les index non clusterisés, faites juste attention à ne pas trop le faire. Si vous ajoutez 10 vues indexées différentes à une table, vous allez voir plus d'impact sur la partie écriture de votre charge de travail, surtout si les colonnes de regroupement ne sont pas (dans) la clé de clustering.
Mon Dieu, je voulais bloguer sur ce sujet.
Les réponses d'Aarons ont bien couvert cette question. Deux choses à ajouter:
J'ai utilisé à la fois des vues d'agrégation et de jointure avec un avantage extrême.
Dans l'ensemble, votre cas d'utilisation semble être un cas parfait. Les vues indexées sont une technique largement sous-utilisée.