Bonsoir à tous !
Si SSIS présente de grands avantages en matière de débugging de part sa conception, il n'en demeure pas moins un outil largement perfectible sur un certain nombre de points.
Le premier d'entre eux est sans doute la faiblesse des bibliothèques de fonctions accessibles dans les tâches de conversions de données. En effet, les tests classiques permettant d'identifier la bonne typologie de la donnée importée dans un Data Flow (ISDATE, ISNUMERIC, ...) ne peuvent pas être effectués autrement qu'à l'aide d'une tâche Script Component... Une tâche souvent fastidieuse et longue à développer, en particulier si le nombre de champs à tester est particulièrement important.
Si devant cette lacune importante la solution de redévelopper un composant spécifique pour SSIS vient immédiatement à l'esprit, la réalité du déploiement sur les postes clients nous rattrape inexorablement. En effet, il est nécessaire de déployer le dit composant sur tous les serveurs impactés ce qui peut s'avérer rapidement délicat...
Je viens donc ici vous proposer une solution alternative, bien que peu satisfaisante pour les perfectionnistes dont je fais partie : l'utilisation de tables temporaires !
En effet, si SSIS ne possède pas les fonctions adéquates, le Transact-SQL peut venir à notre secours !
Il convient donc d'intégrer la source de données dans une table temporaire indépendante du format des données - par exemple des champs VARCHAR - puis d'effectuer les transformations et les vérifications d'intégrité dans le cadre d'une procédure stockée...
Si cette solution demeure peu reluisante, elle reste réellement la seule solution viable tant que SQL Server Integration Services n'offrira pas une bibliothèque de composants et de fonctions satifaisante...
A suivre...
lundi 30 juillet 2007
Déplacement des bases de données système SQL Server 2005...
Bonjour à tous !!!
Voici un post qui ne devrait pas laisser indifférentes les personnes qui ont procédé au déplacement laborieux de toutes les bases d'une instance SQL, en particulier les bases système !
En effet, si le déplacement de ces bases est largement documenté dans la MSDN, il n'en demeure pas moins extrêmement long et fastidieux d'entreprendre une telle opération...
On note cependant l'effort important que Microsoft a consenti pour simplifier ce déplacement entre la version SQL Server 2000 et SQL Server 2005.
Pour mémoire, vous trouverez ici la documentation concernant le déplacement des fichiers des bases de données système de SQL Server 2000 et de SQL Server 7.
Sous SQL Server 2005, seul le déplacement des bases de données Master et mssqlsystemresource, nouvelle base de données qui n'existait pas sous SQL Server 2000, nécessite un traitement particulier.
Je vous propose donc ici un script customisable qui devrait ravir les grands et les petits qui souhaitent déplacer leurs bases de données système SQL Server 2005 en un clic !
Pour exploiter le code suivant, sauvegardez le dans un fichier Visual Basic Script (par exemple c:\movedb.vbs) et lancez le !
Function newliner(s)
newliner = Replace(s,"\n",VBCrLf)
End Function
Sub commande(s)
shcmd.Run "cmd /C " & s,1,true
End Sub
Dim base(4)
base(0) = array("ma","","","","master.mdf","mastlog.ldf")
base(1) = array("rs","mssqlsystemresource","data","log","mssqlsystemresource.mdf","mssqlsystemresource.ldf")
base(2) = array("mo","model","modeldev","modellog","model.mdf","modellog.ldf")
base(3) = array("db","msdb","MSDBData","MSDBLog","MSDBData.mdf","MSDBLog.ldf")
base(4) = array("tp","tempdb","tempdev","templog","tempdb.mdf","templog.ldf")
Function baseray(s)
baseray = array()
For Each row in base
If row(0) = s Then
baseray = row
End If
Next
End Function
' Déplace une base de données autre que "master" et "resource"
Sub movenormal(row, s)
database = row(1)
If s = "d" Then
nom = row(2)
fichier = row(4)
Elseif s = "j" Then
nom = row(3)
fichier = row(5)
End If
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " MODIFY FILE (name=" & nom & ", FILENAME='" & dest & "\" & fichier & "')""")
commande("net stop " & serviceinstance & " /yes")
commande("move """ & src & "\" & fichier & """ """ & dest & """ ")
commande("net start " & serviceinstance)
End Sub
' Déplace "master" et "resource"
Sub movemaster()
row = base(0)
fichierd = row(4)
fichierj = row(5)
commande("net stop " & serviceinstance & " /yes")
'SEARCH and replace parameters
cle = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL\" & keyinstance
cleinstance = shcmd.RegRead(cle)
cle = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\" & cleinstance & "\MSSQLServer\Parameters"
If s = "d" Then
shcmd.RegWrite cle & "\SQLArg0", "-d" & dest & "\" + fichierd, "REG_SZ"
commande("move """ & src & "\" & fichierd & """ """ & dest & """ ")
Elseif s = "j" Then
shcmd.RegWrite cle & "\SQLArg2", "-l" & dest & "\" + fichierj, "REG_SZ"
commande("move """ & src & "\" + fichierj & """ """ & dest & """ ")
End If
commande("net start " + serviceinstance + " /f /T3608")
row = base(1)
database = row(1)
nomd = row(2)
nomj = row(3)
fichierd = row(4)
fichierj = row(5)
If s = "d" Then
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " MODIFY FILE (name=" & nomd & ", FILENAME='" & dest & "\" & fichierd & "')""")
commande("move """ & src & "\" & fichierd & """ """ & dest & """ ")
Elseif s = "j" Then
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " MODIFY FILE (name=" & nomj & ", FILENAME='" & dest & "\" & fichierj & "')""")
commande("move """ & src & "\" & fichierj & """ """ & dest & """ ")
End If
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " SET READ_ONLY""")
commande("net stop " & serviceinstance & " /yes")
commande("net start " & serviceinstance)
End Sub
set shcmd = WScript.CreateObject("WScript.Shell")
' Variables à redéfinir par InputBox ou manuellement:
' nom du serveur SQL et de l'instance dont on déplace les basese
serveur = InputBox("Nom du serveur")
If serveur = "" Then WScript.Quit
instance = InputBox("Nom de l'instance (Pour l'instance par défaut, laisser le champ vide)")
If Replace(instance, " ", "") = "" Then
instance = serveur
serviceinstance = "MSSQLSERVER"
keyinstance = "MSSQLSERVER"
Else
instance = serveur & "\" & instance
serviceinstance = "MSSQL$" & instance
keyinstance = instance
End If
src = InputBox("Chemin source")
dest = InputBox("Chemin destination")
line = "Base(s) à déplacer:\nmr: master + resource\ndb: msdbdata\nmo: model\ntp: tempdb\n(ex: 'mr, tp')"
db = InputBox(newliner(line))
line = "Déplacer (d)onnées, (j)ournaux\n ou les deux (d,j)"
dj = InputBox(newliner(line))
'line = "Paramêtres:\n- source: " + src + "\n- destination: " + dest + "\n- bases: " + db + "\n- objets: " + dj
'msgbox(newliner(line))
dbpar = Split(Replace(db," ",""),",")
djpar = Split(Replace(dj," ",""),",")
For Each db In dbpar
If db <> "mr" Then
r = baseray(db)
If ubound(r) > -1 Then
For Each dj in djpar
movenormal r, dj
Next
End If
Else
movemaster
End If
Next
Bonne journée !
Voici un post qui ne devrait pas laisser indifférentes les personnes qui ont procédé au déplacement laborieux de toutes les bases d'une instance SQL, en particulier les bases système !
En effet, si le déplacement de ces bases est largement documenté dans la MSDN, il n'en demeure pas moins extrêmement long et fastidieux d'entreprendre une telle opération...
On note cependant l'effort important que Microsoft a consenti pour simplifier ce déplacement entre la version SQL Server 2000 et SQL Server 2005.
Pour mémoire, vous trouverez ici la documentation concernant le déplacement des fichiers des bases de données système de SQL Server 2000 et de SQL Server 7.
Sous SQL Server 2005, seul le déplacement des bases de données Master et mssqlsystemresource, nouvelle base de données qui n'existait pas sous SQL Server 2000, nécessite un traitement particulier.
Je vous propose donc ici un script customisable qui devrait ravir les grands et les petits qui souhaitent déplacer leurs bases de données système SQL Server 2005 en un clic !
Pour exploiter le code suivant, sauvegardez le dans un fichier Visual Basic Script (par exemple c:\movedb.vbs) et lancez le !
Function newliner(s)
newliner = Replace(s,"\n",VBCrLf)
End Function
Sub commande(s)
shcmd.Run "cmd /C " & s,1,true
End Sub
Dim base(4)
base(0) = array("ma","","","","master.mdf","mastlog.ldf")
base(1) = array("rs","mssqlsystemresource","data","log","mssqlsystemresource.mdf","mssqlsystemresource.ldf")
base(2) = array("mo","model","modeldev","modellog","model.mdf","modellog.ldf")
base(3) = array("db","msdb","MSDBData","MSDBLog","MSDBData.mdf","MSDBLog.ldf")
base(4) = array("tp","tempdb","tempdev","templog","tempdb.mdf","templog.ldf")
Function baseray(s)
baseray = array()
For Each row in base
If row(0) = s Then
baseray = row
End If
Next
End Function
' Déplace une base de données autre que "master" et "resource"
Sub movenormal(row, s)
database = row(1)
If s = "d" Then
nom = row(2)
fichier = row(4)
Elseif s = "j" Then
nom = row(3)
fichier = row(5)
End If
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " MODIFY FILE (name=" & nom & ", FILENAME='" & dest & "\" & fichier & "')""")
commande("net stop " & serviceinstance & " /yes")
commande("move """ & src & "\" & fichier & """ """ & dest & """ ")
commande("net start " & serviceinstance)
End Sub
' Déplace "master" et "resource"
Sub movemaster()
row = base(0)
fichierd = row(4)
fichierj = row(5)
commande("net stop " & serviceinstance & " /yes")
'SEARCH and replace parameters
cle = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL\" & keyinstance
cleinstance = shcmd.RegRead(cle)
cle = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\" & cleinstance & "\MSSQLServer\Parameters"
If s = "d" Then
shcmd.RegWrite cle & "\SQLArg0", "-d" & dest & "\" + fichierd, "REG_SZ"
commande("move """ & src & "\" & fichierd & """ """ & dest & """ ")
Elseif s = "j" Then
shcmd.RegWrite cle & "\SQLArg2", "-l" & dest & "\" + fichierj, "REG_SZ"
commande("move """ & src & "\" + fichierj & """ """ & dest & """ ")
End If
commande("net start " + serviceinstance + " /f /T3608")
row = base(1)
database = row(1)
nomd = row(2)
nomj = row(3)
fichierd = row(4)
fichierj = row(5)
If s = "d" Then
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " MODIFY FILE (name=" & nomd & ", FILENAME='" & dest & "\" & fichierd & "')""")
commande("move """ & src & "\" & fichierd & """ """ & dest & """ ")
Elseif s = "j" Then
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " MODIFY FILE (name=" & nomj & ", FILENAME='" & dest & "\" & fichierj & "')""")
commande("move """ & src & "\" & fichierj & """ """ & dest & """ ")
End If
commande("sqlcmd -S " & instance & " -Q ""ALTER DATABASE " & database & " SET READ_ONLY""")
commande("net stop " & serviceinstance & " /yes")
commande("net start " & serviceinstance)
End Sub
set shcmd = WScript.CreateObject("WScript.Shell")
' Variables à redéfinir par InputBox ou manuellement:
' nom du serveur SQL et de l'instance dont on déplace les basese
serveur = InputBox("Nom du serveur")
If serveur = "" Then WScript.Quit
instance = InputBox("Nom de l'instance (Pour l'instance par défaut, laisser le champ vide)")
If Replace(instance, " ", "") = "" Then
instance = serveur
serviceinstance = "MSSQLSERVER"
keyinstance = "MSSQLSERVER"
Else
instance = serveur & "\" & instance
serviceinstance = "MSSQL$" & instance
keyinstance = instance
End If
src = InputBox("Chemin source")
dest = InputBox("Chemin destination")
line = "Base(s) à déplacer:\nmr: master + resource\ndb: msdbdata\nmo: model\ntp: tempdb\n(ex: 'mr, tp')"
db = InputBox(newliner(line))
line = "Déplacer (d)onnées, (j)ournaux\n ou les deux (d,j)"
dj = InputBox(newliner(line))
'line = "Paramêtres:\n- source: " + src + "\n- destination: " + dest + "\n- bases: " + db + "\n- objets: " + dj
'msgbox(newliner(line))
dbpar = Split(Replace(db," ",""),",")
djpar = Split(Replace(dj," ",""),",")
For Each db In dbpar
If db <> "mr" Then
r = baseray(db)
If ubound(r) > -1 Then
For Each dj in djpar
movenormal r, dj
Next
End If
Else
movemaster
End If
Next
Bonne journée !
Libellés :
Administration,
SQL Server 2000,
SQL Server 2005,
SQL Server 7
lundi 18 juin 2007
Gestion des requêtes sur les vues partitionnées...
Bonsoir à tous !
Suite à de nombreux problèmes rencontrés avec les vues partitionnées, je souhaite clarifier certaines règles d'usage pour éviter tout problème avec ces éléments capricieux.
Tout d'abord, je voudrai parler du cas des champs date utilisés comme clé de partition. L'optimiseur de SQL Server n'est pas capable d'interpréter correctement les clauses CHECK sur ce type de données.
Le plus simple est alors de créer un champ acceptant l'optimisation des vues partitionnées. Par exemple, le plus simple avec une clé de partition sur l'année est de créer un champ de type INT contenant cette information.
Ainsi, la clé de partition ne sera plus le champ date qui nous posait problème, mais bien le champ INT qui lui sera supporté sans aucun problème.
Je souhaiterai ensuite évoquer les problèmes liés au mode de requêtage. En effet, l'optimiseur de requête de SQL Server effectuant le processus de Paramétrisation avant le processus de Planification de la requête, SQL Server ne procède pas aux optimisations nécessaires lors de la requête suivante :
DECLARE @TEST INT
SET @TEST = 50
SELECT Id, PartitionCol FROM VALL WHERE PartitionCol = @TEST
Nous pouvons alors privilégier le SQL Dynamique dans ce cas bien particulier, seule solution pour obtenir le résultat escompté.
Enfin, je voulai attirer ici l'attention sur l'importance des statistiques dans le cadre de l'utilisation des vues partitionnées. En effet, de mauvaises statistiques induisent le stockage d'un mauvais plan d'exécution. Les performances s'en ressentent alors de façon très importante, en particulier dans le cadre de l'utilisation de procédures stockées, où en cas de paramétrisation des requêtes ad hoc.
Bonne soirée !
Suite à de nombreux problèmes rencontrés avec les vues partitionnées, je souhaite clarifier certaines règles d'usage pour éviter tout problème avec ces éléments capricieux.
Tout d'abord, je voudrai parler du cas des champs date utilisés comme clé de partition. L'optimiseur de SQL Server n'est pas capable d'interpréter correctement les clauses CHECK sur ce type de données.
Le plus simple est alors de créer un champ acceptant l'optimisation des vues partitionnées. Par exemple, le plus simple avec une clé de partition sur l'année est de créer un champ de type INT contenant cette information.
Ainsi, la clé de partition ne sera plus le champ date qui nous posait problème, mais bien le champ INT qui lui sera supporté sans aucun problème.
Je souhaiterai ensuite évoquer les problèmes liés au mode de requêtage. En effet, l'optimiseur de requête de SQL Server effectuant le processus de Paramétrisation avant le processus de Planification de la requête, SQL Server ne procède pas aux optimisations nécessaires lors de la requête suivante :
DECLARE @TEST INT
SET @TEST = 50
SELECT Id, PartitionCol FROM VALL WHERE PartitionCol = @TEST
Nous pouvons alors privilégier le SQL Dynamique dans ce cas bien particulier, seule solution pour obtenir le résultat escompté.
Enfin, je voulai attirer ici l'attention sur l'importance des statistiques dans le cadre de l'utilisation des vues partitionnées. En effet, de mauvaises statistiques induisent le stockage d'un mauvais plan d'exécution. Les performances s'en ressentent alors de façon très importante, en particulier dans le cadre de l'utilisation de procédures stockées, où en cas de paramétrisation des requêtes ad hoc.
Bonne soirée !
Libellés :
Développement,
SQL Server 2000,
SQL Server 2005
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 !
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 !
Libellés :
Développement,
SQL Server 2000,
SQL Server 2005
jeudi 31 mai 2007
Haute disponibilité et licences SQL Server 2005
Bonsoir !
En attendant que je trouve une solution pour publier un post qui me tient à coeur, je viens vous parler d'un sujet qui intéresse un jour ou l'autre tout le monde : les sous !
En effet, la mise en oeuvre d'une solution de haute disponibilité est souvent vue par beaucoup de clients comme un poste financier des plus onéreux. Je viens ici démonter ces préjugés... La politique de licences de SQL Server 2005 permet aux sociétés disposant de moyens financiers limités d'obtenir une solution robuste à faible coût.
Le premier des préjugés que je voudrais casser ici, sans doute lié à la réalité de la version précédente de SQL Server, c'est que SQL Server 2005 ne nécessite pas l'acquisition d'une édition Entreprise pour permettre de mettre en oeuvre une solution de haute disponibilité. En effet, l'édition Standard supporte les solutions de mirroring, de clustering et de log shipping... Et bien entendu, la distribution des données !
Le deuxième est un aspect de licence qui revient souvent dans mes entretiens avec mes clients : les solutions de haute disponibilités telles que le mirroring et le clustering étant des solutions dites "Actif-Passif" - comprenez que le serveur de backup est en position d'attente et ne peut servir l'utilisateur - Microsoft considère que vous n'avez pas à investir dans une licence pour votre serveur de backup si celui-ci ne remplace pas le serveur principal plus de 30 jours par an !
Bien entendu, des limites existent, puisque, par exemple, le mirroring proposé dans l'édition Standard ne supporte que 2 noeuds d'au plus 2 processeurs chacun... Mais quand on rappelle que le serveur témoin peut être matérialisé par un simple SQL Server 2005 Express, il apparaît évident que SQL Server 2005 propose une solution de haute disponibilité tout à fait accessible.
A très bientôt !
En attendant que je trouve une solution pour publier un post qui me tient à coeur, je viens vous parler d'un sujet qui intéresse un jour ou l'autre tout le monde : les sous !
En effet, la mise en oeuvre d'une solution de haute disponibilité est souvent vue par beaucoup de clients comme un poste financier des plus onéreux. Je viens ici démonter ces préjugés... La politique de licences de SQL Server 2005 permet aux sociétés disposant de moyens financiers limités d'obtenir une solution robuste à faible coût.
Le premier des préjugés que je voudrais casser ici, sans doute lié à la réalité de la version précédente de SQL Server, c'est que SQL Server 2005 ne nécessite pas l'acquisition d'une édition Entreprise pour permettre de mettre en oeuvre une solution de haute disponibilité. En effet, l'édition Standard supporte les solutions de mirroring, de clustering et de log shipping... Et bien entendu, la distribution des données !
Le deuxième est un aspect de licence qui revient souvent dans mes entretiens avec mes clients : les solutions de haute disponibilités telles que le mirroring et le clustering étant des solutions dites "Actif-Passif" - comprenez que le serveur de backup est en position d'attente et ne peut servir l'utilisateur - Microsoft considère que vous n'avez pas à investir dans une licence pour votre serveur de backup si celui-ci ne remplace pas le serveur principal plus de 30 jours par an !
Bien entendu, des limites existent, puisque, par exemple, le mirroring proposé dans l'édition Standard ne supporte que 2 noeuds d'au plus 2 processeurs chacun... Mais quand on rappelle que le serveur témoin peut être matérialisé par un simple SQL Server 2005 Express, il apparaît évident que SQL Server 2005 propose une solution de haute disponibilité tout à fait accessible.
A très bientôt !
Libellés :
Configuration système,
Information,
SQL Server 2005
mardi 22 mai 2007
Incorporer des rapports Reporting Services 2005 dans une application Web
Bonjour à tous !
Au cours des différents ateliers et des formations que j'ai animés sur Reporting Services 2005, une question revient régulièrement : l'interopérabilité.
En effet, si Reporting Services est très bien intégré dans le monde .Net, notamment avec le composant ReportViewer, comment peut-on intégrer un rapport dans une page ASP classique ? Comment piloter Reporting Services depuis une simple FRAME ?
Si l'intégration de Reporting Services à travers l'URL du serveur de rapports est relativement simple, il n'en est en revanche pas de même pour les paramètres permettant de personnaliser l'affichage. Et rares sont les éléments de documentation à notre disposition. Je propose donc ici une sélection de paramètres utiles pour l'intégration de rapports Reporting Services dans des pages Web.
Créons par exemple le rapport "Mon Rapport.rdl" que l'on stocke dans un nouveau répertoire "Test" de notre serveur Reporting Services.
De façon à tester tous les paramètres, nous ajoutons un paramètre à notre rapport nommé "DateDuJour".
Par défaut, l'URL http://localhost/ReportServer?%2fTest%2fMon+Rapport me permet d'obtenir mon rapport - en partant bien entendu du postulat que le serveur de rapports se trouve bien à l'adresse http://localhost/ReportServer et que le gestionnaire de rapports se situe à l'adresse http://localhost/Reports.
Il est possible d'éviter à l'utilisateur d'avoir à saisir le paramètre en ajoutant la valeur du paramètre dans l'URL :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&DateDuJour=01/01/2007
Cependant, le rendu obtenu présente toujours une lourde barre d'outils et permet à l'utilisateur de modifier selon sa volonté les paramètres du rapport.
Il existe en fait de nombreux paramètres permettant de personnaliser l'affichage de notre rapport. Nous en distinguons 2 grandes catégories :
- Les paramètres du serveur préfixés par le namespace rs,
- Les paramètres de rendu des composants préfixés par le namespace rc.
Voici donc les paramètres du serveur les plus utiles :
- rs:Command
Ce paramètre définit l'action menée par le serveur. Par défaut, la valeur de ce paramètre est définie à "Render" pour les rapports et "ListChildren" pour les dossiers.
On trouve également deux autres valeurs possibles de ce paramètre : "GetRessourceContents" et "GetDataSourceContents".
Si l'on spécifie ce paramètre, l'URL de notre rapport devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&DateDuJour=01/01/2007
- rs:Format
Le format est sans aucun doute l'un des paramètres préférés des utilisateurs. Il permet en effet de définir le format du rendu parmi les formats existants (HTML3.2, HTML4.0, HTMLOWC, MHTML, IMAGE, EXCEL, CSV, PDF, XML) ou d'autres extensions si elles sont disponibles sur le serveur.
Ainsi, si l'on souhaite obtenir notre rapport en PDF, l'URL de notre rapport devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:Format=PDF&DateDuJour=01/01/2007
- rs:ParameterLanguage
Ce paramètre permet de s'affranchir de la culture du navigateur client en spécifiant une culture spécifique. La valeur par défaut est la valeur du navigateur client.
Nous pouvons par exemple forcer la culture de notre rapport en utilisant l'URL suivante :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:ParameterLanguage=fr-FR&DateDuJour=01/01/2007
- rs:Snapshot
Le paramètre Snapshot permet d'utiliser la capture d'un rapport effectuée à une date et une heure précises. Cette capture instantanée est stockée dans la base de données Reporting Services.
Ce paramètre reçoit une date longue sans timezone. Notre URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:Snapshot=2007-05-22T15:41:08
Ce paramètre nécessite bien évidemment que l'historique du rapport soit activée.
- rs:ClearSession
Ce paramètre permet de forcer le navigateur à vider son cache et à recharger une nouvelle version du rapport.
Dans notre cas, l'URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:ClearSession=true&DateDuJour=01/01/2007
- rs:SessionID
Un paramètre qui permet d'identifier une session active lorsque le serveur de rapport n'utilise pas les cookies.
L'URL prend alors la forme suivante :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:SessionID=uwoits45rufhhg55f2i3hm55&DateDuJour=01/01/2007
Etudions maintenant quelques paramètres de rendu utiles :
- rc:Toolbar
Ce paramètre permet d'afficher ou de cacher la totalité de la barre d'outils.
Par exemple, si nous souhaitons cacher la barre d'outils, notre URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Toolbar=false&DateDuJour=01/01/2007
La valeur par défaut est évidemment définie à "true".
- rc:Parameters
Ce paramètre permet de ne cacher que la partie édition des paramètres du rapport de la barre d'outils. La valeur de ce paramètre n'a donc pas d'incidence si le précédent est défini à "false".
Ainsi, si nous souhaitons que les paramètres du rapport restent figés, notre URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Parameters=false&DateDuJour=01/01/2007
La valeur par défaut est évidemment définie à "true".
- rc:Section
Ce paramètre permet d'afficher la page du rapport souhaitée. Par défaut, Reporting Services affiche la première page du rapport.
Pour afficher la deuxième page, nous écrivons :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Section=2&DateDuJour=01/01/2007
Ce paramètre est particulièrement utile si l'on souhaite développer sa propre barre d'outils.
- rc:Zoom
Il s'agit d'un paramètre de rendu ne fonctionnant qu'avec les versions d'Internet Explorer 5.0 ou ultérieures.
Les valeurs possibles pour ce paramètre sont :
* "page+width" pour occuper toute la largeur du navigateur,
* "whole+page" pour optimiser l'espace dans le navigateur pour visualiser le rapport sur une seule page,
* un entier correspondant à un pourcentage ; la valeur par défaut est "100".
- rc:LinkTarget
Utile si votre rapport contient des hyperliens, ce paramètre permet de préciser la fenêtre ou la frame de destination des liens de votre rapport.
Les différentes valeurs possibles sont entre autres :
* "_blank",
* "_self",
* "_parent",
* "_top",
* Ou tout autre nom de cible valide.
- rc:FindString, rc:StartFind, rc:EndFind
Le paramètre rc:FindString permet de filtrer les enregistrements du rapport. Ce paramètre est souvent utilisé conjointement avec les paramètres rc:StartFind et rc:EndFind qui permettent de borner la recherche.
Par exemple, pour rechercher la chaîne de caractères "Test" dans les 2 premières pages du rapport, l'URL sera :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rc:FindString=Test&rc:StartFind=1&rc:EndFind=2&DateDuJour=01/01/2007
- rc:Stylesheet
Le dernier paramètre que je développerai dans ce post permet de définir une feuille de style à appliquer sur le rapport.
La feuille de style CSS doit être présente dans le répertoire des styles, par défaut :
C:\Program Files\Microsoft SQL Server\MSSQL\Reporting Services\ReportServer\Styles
Pour appliquer la feuille de style "MonStyle.css", l'URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Stylesheet=MonStyle&DateDuJour=01/01/2007
On notera tout comme pour l'appel du rapport l'absence d'extension.
Je concluerai par le fait que la majeure partie des paramètres présentés ici sont valables dès les services packs de Reporting Services 2000, et que par conséquent cet article ne s'adresse pas uniquement aux utilisateurs de Reporting Services 2005.
A bientôt pour un autre article !
Au cours des différents ateliers et des formations que j'ai animés sur Reporting Services 2005, une question revient régulièrement : l'interopérabilité.
En effet, si Reporting Services est très bien intégré dans le monde .Net, notamment avec le composant ReportViewer, comment peut-on intégrer un rapport dans une page ASP classique ? Comment piloter Reporting Services depuis une simple FRAME ?
Si l'intégration de Reporting Services à travers l'URL du serveur de rapports est relativement simple, il n'en est en revanche pas de même pour les paramètres permettant de personnaliser l'affichage. Et rares sont les éléments de documentation à notre disposition. Je propose donc ici une sélection de paramètres utiles pour l'intégration de rapports Reporting Services dans des pages Web.
Créons par exemple le rapport "Mon Rapport.rdl" que l'on stocke dans un nouveau répertoire "Test" de notre serveur Reporting Services.
De façon à tester tous les paramètres, nous ajoutons un paramètre à notre rapport nommé "DateDuJour".
Par défaut, l'URL http://localhost/ReportServer?%2fTest%2fMon+Rapport me permet d'obtenir mon rapport - en partant bien entendu du postulat que le serveur de rapports se trouve bien à l'adresse http://localhost/ReportServer et que le gestionnaire de rapports se situe à l'adresse http://localhost/Reports.
Il est possible d'éviter à l'utilisateur d'avoir à saisir le paramètre en ajoutant la valeur du paramètre dans l'URL :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&DateDuJour=01/01/2007
Cependant, le rendu obtenu présente toujours une lourde barre d'outils et permet à l'utilisateur de modifier selon sa volonté les paramètres du rapport.
Il existe en fait de nombreux paramètres permettant de personnaliser l'affichage de notre rapport. Nous en distinguons 2 grandes catégories :
- Les paramètres du serveur préfixés par le namespace rs,
- Les paramètres de rendu des composants préfixés par le namespace rc.
Voici donc les paramètres du serveur les plus utiles :
- rs:Command
Ce paramètre définit l'action menée par le serveur. Par défaut, la valeur de ce paramètre est définie à "Render" pour les rapports et "ListChildren" pour les dossiers.
On trouve également deux autres valeurs possibles de ce paramètre : "GetRessourceContents" et "GetDataSourceContents".
Si l'on spécifie ce paramètre, l'URL de notre rapport devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&DateDuJour=01/01/2007
- rs:Format
Le format est sans aucun doute l'un des paramètres préférés des utilisateurs. Il permet en effet de définir le format du rendu parmi les formats existants (HTML3.2, HTML4.0, HTMLOWC, MHTML, IMAGE, EXCEL, CSV, PDF, XML) ou d'autres extensions si elles sont disponibles sur le serveur.
Ainsi, si l'on souhaite obtenir notre rapport en PDF, l'URL de notre rapport devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:Format=PDF&DateDuJour=01/01/2007
- rs:ParameterLanguage
Ce paramètre permet de s'affranchir de la culture du navigateur client en spécifiant une culture spécifique. La valeur par défaut est la valeur du navigateur client.
Nous pouvons par exemple forcer la culture de notre rapport en utilisant l'URL suivante :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:ParameterLanguage=fr-FR&DateDuJour=01/01/2007
- rs:Snapshot
Le paramètre Snapshot permet d'utiliser la capture d'un rapport effectuée à une date et une heure précises. Cette capture instantanée est stockée dans la base de données Reporting Services.
Ce paramètre reçoit une date longue sans timezone. Notre URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:Snapshot=2007-05-22T15:41:08
Ce paramètre nécessite bien évidemment que l'historique du rapport soit activée.
- rs:ClearSession
Ce paramètre permet de forcer le navigateur à vider son cache et à recharger une nouvelle version du rapport.
Dans notre cas, l'URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:ClearSession=true&DateDuJour=01/01/2007
- rs:SessionID
Un paramètre qui permet d'identifier une session active lorsque le serveur de rapport n'utilise pas les cookies.
L'URL prend alors la forme suivante :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rs:SessionID=uwoits45rufhhg55f2i3hm55&DateDuJour=01/01/2007
Etudions maintenant quelques paramètres de rendu utiles :
- rc:Toolbar
Ce paramètre permet d'afficher ou de cacher la totalité de la barre d'outils.
Par exemple, si nous souhaitons cacher la barre d'outils, notre URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Toolbar=false&DateDuJour=01/01/2007
La valeur par défaut est évidemment définie à "true".
- rc:Parameters
Ce paramètre permet de ne cacher que la partie édition des paramètres du rapport de la barre d'outils. La valeur de ce paramètre n'a donc pas d'incidence si le précédent est défini à "false".
Ainsi, si nous souhaitons que les paramètres du rapport restent figés, notre URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Parameters=false&DateDuJour=01/01/2007
La valeur par défaut est évidemment définie à "true".
- rc:Section
Ce paramètre permet d'afficher la page du rapport souhaitée. Par défaut, Reporting Services affiche la première page du rapport.
Pour afficher la deuxième page, nous écrivons :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Section=2&DateDuJour=01/01/2007
Ce paramètre est particulièrement utile si l'on souhaite développer sa propre barre d'outils.
- rc:Zoom
Il s'agit d'un paramètre de rendu ne fonctionnant qu'avec les versions d'Internet Explorer 5.0 ou ultérieures.
Les valeurs possibles pour ce paramètre sont :
* "page+width" pour occuper toute la largeur du navigateur,
* "whole+page" pour optimiser l'espace dans le navigateur pour visualiser le rapport sur une seule page,
* un entier correspondant à un pourcentage ; la valeur par défaut est "100".
- rc:LinkTarget
Utile si votre rapport contient des hyperliens, ce paramètre permet de préciser la fenêtre ou la frame de destination des liens de votre rapport.
Les différentes valeurs possibles sont entre autres :
* "_blank",
* "_self",
* "_parent",
* "_top",
* Ou tout autre nom de cible valide.
- rc:FindString, rc:StartFind, rc:EndFind
Le paramètre rc:FindString permet de filtrer les enregistrements du rapport. Ce paramètre est souvent utilisé conjointement avec les paramètres rc:StartFind et rc:EndFind qui permettent de borner la recherche.
Par exemple, pour rechercher la chaîne de caractères "Test" dans les 2 premières pages du rapport, l'URL sera :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rc:FindString=Test&rc:StartFind=1&rc:EndFind=2&DateDuJour=01/01/2007
- rc:Stylesheet
Le dernier paramètre que je développerai dans ce post permet de définir une feuille de style à appliquer sur le rapport.
La feuille de style CSS doit être présente dans le répertoire des styles, par défaut :
C:\Program Files\Microsoft SQL Server\MSSQL\Reporting Services\ReportServer\Styles
Pour appliquer la feuille de style "MonStyle.css", l'URL devient :
http://localhost/ReportServer?%2fTest%2fMon+Rapport&rs:Command=Render&rc:Stylesheet=MonStyle&DateDuJour=01/01/2007
On notera tout comme pour l'appel du rapport l'absence d'extension.
Je concluerai par le fait que la majeure partie des paramètres présentés ici sont valables dès les services packs de Reporting Services 2000, et que par conséquent cet article ne s'adresse pas uniquement aux utilisateurs de Reporting Services 2005.
A bientôt pour un autre article !
Libellés :
Développement,
Reporting Services 2000,
Reporting Services 2005
lundi 2 avril 2007
Maintenance des index SQL Server - Défragmentation et réindexation
Bonjour à tous !
Je rencontre de plus en plus fréquemment le problème de la fragmentation des index.
En effet, lorsqu'un fort volume de données est inséré dans une table sans que cela ne soit prévu lors de la conception de la base de données, les index croissent de manière désordonnée...
Pour détecter une telle fragmentation, SQL Server 2000 offre la commande suivante :
DBCC SHOWCONTIG
Si cette commande est toujours disponible sous SQL Server 2005 - et sera amenée à disparaitre dans les versions futures -, ce dernier fournit d'autres outils plus ergonomiques et plus précis pour les administrateurs. Parmi ces outils, on notera notamment la fonction dynamique suivante :
sys.dm_db_index_physical_stats
Il existe plusieurs façons de corriger le problème de la fragmentation. Mais avant de voir ces différentes techniques, attachons-nous tout d'abord à la façon dont l'on peut éviter que cette fragmentation ne se produise...
En réalité, tout dépend du mode d'alimentation de la base de données. En effet, un batch de chargement sera traité différemment d'une insertion unitaire.
De la même manière, le milieu fonctionnel impose des contraites ne permettant pas toujours l'emploi de certaines techniques.
Voyons tout d'abord le cas du batch de chargement : lors de l'exécution d'un batch, nous insérons généralement de grandes quantité de données. Ces batches s'exécutent habituellement de nuit, période de faible activité pour la base de données.
Dans ce cas, nous privilégierons la suppression de tous les index avant le chargement, et la recréation de ces index à la fin. Ceci présente un double avantage :
- D'une part les index regénérés ne sont pas fragmentés, puisque tout frais
- D'autre part le chargement des données est beaucoup plus rapide
Je rappellerai ici que la clé primaire incluant un index unique doit également être supprimée dans ce cas - parce que non, ça n'arrive jamais qu'il y ait des personnes qui suppriment tous les index sauf celui de la clé primaire ;-).
Bien entendu, cette suppression des index implique une absence d'activité sur la base de données sur une plage horaire donnée.
Dans le cas des insertions unitaires, le volume de ces insertions est généralement prévisible et plus faible. Dans ces conditions, le mieux est de dimensionner le FILLFACTOR de l'index à une valeur assurant un espace suffisant pour son développement.
Attention à ne pas tomber dans l'excès tout de même : un FILLFACTOR inférieur à 50 dégrade très fortement les performances et s'avère donc plus pénalisant que la fragmentation des index.
Attachons-nous maintenant à une table dont les index sont largement fragmentés.
Une solution simple reste la suppression des index pour les recréer. Cette solution présente l'avantage de toujours donner satisfaction et d'éviter l'explosion des groupes de fichiers.
Cette solution peut être effectuée dans un script traditionnel (DROP/CREATE) ou à l'aide de la commande DBCC DBREINDEX.
L'inconvénient majeur de cette méthode reste la période d'inactivité de la base de données nécessaire pour la reconstruction des index, car ces opérations sont des opérations OFFLINE.
La commande DBCC DBREINDEX, toujours présente dans SQL Server 2005, possède un équivalent avec la commande ALTER INDEX avec l'option REBUILD.
L'autre solution est la défragmentation (DBCC INDEXDEFRAG). Cette solution est une solution ONLINE. C'est la principale raison d'être de l'utilisation de cette commande. Cependant, il faut prendre garde à n'effectuer cette opération qu'après le chargement et non pas en parallèle au risque d'être totalement inefficace.
Le principal inconvénient de cette solution est la place nécessaire sur les groupes de fichiers. En effet, la défragmentation déplace des blocs de données vers des emplacements libres, et par conséquent pose rapidement des problèmes de taille des groupes de fichiers si la fragmentation est très importante. De plus la défragmentation est une opération entièrement loggée générant de fait de très gros volumes dans les journaux de transactions.
Là encore, SQL Server 2005 autorise toujours la commande DBCC INDEXDEFRAG, destinée à disparaître au profit du ALTER INDEX avec l'option REORGANIZE.
En conclusion, voici un récapitulatif des points importants :
- La première des choses est de s'assurer dans le cadre du développement de la base de données que notre base de données ne se fragmentera pas ou peu. Pour cela, il ne faut pas hésiter à supprimer les index et à les recréer au cours des processus d'alimentation. La fragmentation des index n'est pas une fatalité.
- Par la suite, un examen régulier de l'état de la base de données permet de surveiller l'évolution des index et le cas échéant d'entreprendre des actions.
- Sous SQL Server 2000, on privilégiera la commande atomique DBCC DBREINDEX si l'opération peut être menée OFFLINE. On restreindra donc l'usage de la commande DBCC INDEXDEFRAG aux cas nécessitant que les données restent ONLINE.
- Sous SQL Server 2005, on utilisera la commande ALTER INDEX avec les options REBUILD et REORGANIZE qui vont bien, cette commande étant la seule destinée à être maintenue dans les prochaines versions de SQL Server.
Je rencontre de plus en plus fréquemment le problème de la fragmentation des index.
En effet, lorsqu'un fort volume de données est inséré dans une table sans que cela ne soit prévu lors de la conception de la base de données, les index croissent de manière désordonnée...
Pour détecter une telle fragmentation, SQL Server 2000 offre la commande suivante :
DBCC SHOWCONTIG
Si cette commande est toujours disponible sous SQL Server 2005 - et sera amenée à disparaitre dans les versions futures -, ce dernier fournit d'autres outils plus ergonomiques et plus précis pour les administrateurs. Parmi ces outils, on notera notamment la fonction dynamique suivante :
sys.dm_db_index_physical_stats
Il existe plusieurs façons de corriger le problème de la fragmentation. Mais avant de voir ces différentes techniques, attachons-nous tout d'abord à la façon dont l'on peut éviter que cette fragmentation ne se produise...
En réalité, tout dépend du mode d'alimentation de la base de données. En effet, un batch de chargement sera traité différemment d'une insertion unitaire.
De la même manière, le milieu fonctionnel impose des contraites ne permettant pas toujours l'emploi de certaines techniques.
Voyons tout d'abord le cas du batch de chargement : lors de l'exécution d'un batch, nous insérons généralement de grandes quantité de données. Ces batches s'exécutent habituellement de nuit, période de faible activité pour la base de données.
Dans ce cas, nous privilégierons la suppression de tous les index avant le chargement, et la recréation de ces index à la fin. Ceci présente un double avantage :
- D'une part les index regénérés ne sont pas fragmentés, puisque tout frais
- D'autre part le chargement des données est beaucoup plus rapide
Je rappellerai ici que la clé primaire incluant un index unique doit également être supprimée dans ce cas - parce que non, ça n'arrive jamais qu'il y ait des personnes qui suppriment tous les index sauf celui de la clé primaire ;-).
Bien entendu, cette suppression des index implique une absence d'activité sur la base de données sur une plage horaire donnée.
Dans le cas des insertions unitaires, le volume de ces insertions est généralement prévisible et plus faible. Dans ces conditions, le mieux est de dimensionner le FILLFACTOR de l'index à une valeur assurant un espace suffisant pour son développement.
Attention à ne pas tomber dans l'excès tout de même : un FILLFACTOR inférieur à 50 dégrade très fortement les performances et s'avère donc plus pénalisant que la fragmentation des index.
Attachons-nous maintenant à une table dont les index sont largement fragmentés.
Une solution simple reste la suppression des index pour les recréer. Cette solution présente l'avantage de toujours donner satisfaction et d'éviter l'explosion des groupes de fichiers.
Cette solution peut être effectuée dans un script traditionnel (DROP/CREATE) ou à l'aide de la commande DBCC DBREINDEX.
L'inconvénient majeur de cette méthode reste la période d'inactivité de la base de données nécessaire pour la reconstruction des index, car ces opérations sont des opérations OFFLINE.
La commande DBCC DBREINDEX, toujours présente dans SQL Server 2005, possède un équivalent avec la commande ALTER INDEX avec l'option REBUILD.
L'autre solution est la défragmentation (DBCC INDEXDEFRAG). Cette solution est une solution ONLINE. C'est la principale raison d'être de l'utilisation de cette commande. Cependant, il faut prendre garde à n'effectuer cette opération qu'après le chargement et non pas en parallèle au risque d'être totalement inefficace.
Le principal inconvénient de cette solution est la place nécessaire sur les groupes de fichiers. En effet, la défragmentation déplace des blocs de données vers des emplacements libres, et par conséquent pose rapidement des problèmes de taille des groupes de fichiers si la fragmentation est très importante. De plus la défragmentation est une opération entièrement loggée générant de fait de très gros volumes dans les journaux de transactions.
Là encore, SQL Server 2005 autorise toujours la commande DBCC INDEXDEFRAG, destinée à disparaître au profit du ALTER INDEX avec l'option REORGANIZE.
En conclusion, voici un récapitulatif des points importants :
- La première des choses est de s'assurer dans le cadre du développement de la base de données que notre base de données ne se fragmentera pas ou peu. Pour cela, il ne faut pas hésiter à supprimer les index et à les recréer au cours des processus d'alimentation. La fragmentation des index n'est pas une fatalité.
- Par la suite, un examen régulier de l'état de la base de données permet de surveiller l'évolution des index et le cas échéant d'entreprendre des actions.
- Sous SQL Server 2000, on privilégiera la commande atomique DBCC DBREINDEX si l'opération peut être menée OFFLINE. On restreindra donc l'usage de la commande DBCC INDEXDEFRAG aux cas nécessitant que les données restent ONLINE.
- Sous SQL Server 2005, on utilisera la commande ALTER INDEX avec les options REBUILD et REORGANIZE qui vont bien, cette commande étant la seule destinée à être maintenue dans les prochaines versions de SQL Server.
Libellés :
Administration,
Développement,
SQL Server 2000,
SQL Server 2005
Inscription à :
Articles (Atom)