lundi 18 juin 2007

Optimisation des requêtes à l'aide des vues partitionnées

Bonjour à tous !

Les vues partitionnées, tout comme les tables partagées dans SQL Server 2005, sont un moyen simple de répartir ses données sur plusieurs filegroups afin d'alléger les coûts de maintenance. Il est même possible à l'aide des vues partitionnées distribuées de répartir la charge, tout simplement en stockant les différentes tables sur différents serveurs.
Les vues partitionnées regroupent donc les données de plusieurs tables dont la structure est identique. Ainsi, toutes les opérations d'insertion, de modification et de suppression peuvent être effectuées sur une vue partitionnée, moyennant une condition sine qua non : la clé de répartion doit faire partie de la clé primaire de chacune des tables aggrégées.

Si les vues partitionnées sont très couramment utilisées pour aggréger les données dans le cadre d'infocentres multisites, les vues partitionnées n'en demeurent pas moins la seule façon de faire du partitionnement horizontal sous SQL Server 2000.
Dès lors, ces vues s'avèrent incontournables sous SQL Server 2000 pour architecturer une solution à forte volumétrie ou disposant d'une fenêtre de données glissante - dans ce cas particulier, la clé de répartition est couramment la date.

Afin de mieux comprendre comment optimiser une vue partitionnée, commençons par un exemple. Créons deux tables possédant la même structure.
CREATE TABLE TB1 (Id INT NOT NULL CONSTRAINT PK_TB1 PRIMARY KEY, PartitionCol INT NOT NULL)
CREATE TABLE TB2 (Id INT NOT NULL CONSTRAINT PK_TB2 PRIMARY KEY, PartitionCol INT NOT NULL)


La vue suivante est alors la vue "partitionnée" qui permet de concaténer les données de ces deux tables :
CREATE VIEW VALL AS SELECT Id, PartitionCol FROM TB1 UNION SELECT Id, PartitionCol FROM TB2

Cependant, cette vue est loin d'optimiser les performances, effectuant même une tâche de reconnaissance afin d'éviter les doublons.
Admettons maintenant que nos données soient réparties de façon bien distincte selon la clé de répartition. Nous pouvons alors de façon sûre écrire :
ALTER VIEW VALL AS SELECT Id, PartitionCol FROM TB1 UNION ALL SELECT Id, PartitionCol FROM TB2

Cette vue est maintenant nettement plus performante, mais reste toujours sans grand intérêt.
Appliquons maintenant des contraintes de type CHECK afin d'assurer au système la bonne séparation des données, par exemple en séparant les éléments négatifs des éléments positifs :
ALTER TABLE TB1 ADD CONSTRAINT CK_TB1_PartitionCol CHECK (PartitionCol < 0)
ALTER TABLE TB2 ADD CONSTRAINT CK_TB2_PartitionCol CHECK (PartitionCol >= 0)


En exploitant notre vue à l'aide de la commande suivante, on obtient enfin le résultat attendu :
SELECT Id, PartitionCol FROM VALL WHERE PartitionCol = 50

En effet, on peut voir dans le plan d'exécution de notre requête que seule la table TB2 est effectivement requêtée.

Nous pouvons maintenant procéder à la dernière étape de l'optimisation de notre vue partitionnée. Pour cela il nous faut ajouter notre clé de répartition dans la clé primaire. Ainsi, nous pourrons utiliser notre vue partitionnée pour insérer et modifier nos données.
ALTER TABLE TB1 DROP CONSTRAINT PK_TB1
ALTER TABLE TB1 ADD CONSTRAINT PK_TB1 PRIMARY KEY (Id, PartitionCol)
ALTER TABLE TB2 DROP CONSTRAINT PK_TB2
ALTER TABLE TB2 ADD CONSTRAINT PK_TB2 PRIMARY KEY (Id, PartitionCol)


La commande suivante est alors possible !!!
INSERT INTO VALL (Id, PartitionCol) VALUES (10, 1000)

Je conviens aisément que ces vues partitionnées présentent de nombreuses difficultés d'implémentation, et qu'en matière de "fenêtre glissante", rien ne vaut les tables partitionnées de SQL Server 2005. En revanche, qu'il s'agisse d'une architecture sous SQL Server 2000 ou une architecture distribuée sur plusieurs serveurs, les vues partitionnées s'avèrent être une arme redoutable dans l'arsenal du développeur Base de Données.

A bientôt, et tous à vos benchs !

Aucun commentaire: