jeudi 23 octobre 2008

Racket virtuel dans un monde réèl

De nos jours, je crois que la plupart des parents font attention aux problèmes de racket scolaire.Ainsi, il est courant de voir des parents conseiller à leur enfant de ne pas prendre sa console de jeux portable, de faire attention à son GSM, son lecteur MP3, de ne pas ostensiblement arborer des signes de richesse, etc.
Bref, le parfait manuel pour retrouver nos enfants en vie chaque soir....

Maintenant, il faudra également mettre nos enfants en garde contre le racket virtuel.
Avoir des objets dans un monde/jeu virtuel peut également motiver la convoitise.
Ansi, deux adolescents des Pays-Bas viennent de se faire condamner pour racket virtuel.

Cela semble peut être ridicule... mais réalisez quand même qu'un gosse s'est retrouvé tabassé et menacé avec un couteau pour céder une amulette qu'il possédait dans un jeu en ligne!

Source: Cet article sur PCInpact.

mercredi 22 octobre 2008

Generation PDF

Voici quelques références utiles concernant la génération de document PDF:

Outil de conversion pour application WEB:
  • Prince pour la génération PDF depuis des documents html, css et XML.
    Prince est utilisé par Google Doc.
  • Apache FOP permet également la génération de documents en ligne mais bassé sur des documents XML et une XSL-FO (formatting Object)
 Applications pour Windows:
 Références:

dimanche 19 octobre 2008

SQL Server Training - Estimated Execution plan

L'affichage du plan d'exécution est possible de différentes façon (entre autre via l'interface du SQL Analyser ou via SET STATISTICS XML ON).
Un précédent article sur les stored procedure traitait de cet activation.
Celui ci, plus pragmatique, fournira quelqyes de détails utiles pour la lecture du plan d'exécution.

Les flux d'informations
Les flux d'informations sont symbolisés par des flèches plus ou moins épaisses.
Plus elles sont épaisses, plus le flux d'information est gros (en terme de milliers de records).
Il va de soi que les flux d'informations en amont du plan d'exécution (les sélections de données depuis la DB) doivent être aussi restreints que possible.
Plus ils seront importants et plus le coût s'en ressentira sur le temps de traitement (jointure, tri, filtrage) et la consommation de la mémoire de travail.

Les jointures
En interne, l'engine SQL utilise plusieurs algorithmes pour joindre des rowset de source différentes.
Parmis ces algorithmes, il y a:
  1. Le Merge Join.
  2. Le Hash Join.
  3. Le Nested Loop Join
Le Merge Join
Le merge join est l'opération la moins couteuse et la plus rapide.
Les deux rowsets peuvent être joints en une seule opération continue.
Cette opération n'est possible que si les deux rowset sont stockés (produit) avec le même tri.

Le Hash Join
Opération plus couteuse que le merge join et donc plus lente. Dans ce cas de figure, une clé de hashage doit être produite sur les données avant une opération de Merge Join.
Cet opération nécessite l'usage d'une "table temporaire" pour stocker les résultats intermédiaires, elle est donc gourmande en mémoire.

Le Nested Loop Join
L'opération Nested Loop est sans conteste l'opération la plus couteuse (et de loin). 
Pour chaque entrée d'un rowset, SQL Serveur effectue une opération de recherche dans le second. Le Nested Loop Join a donc des performances catastrophiques.
Cette jointure n'est envisagée par SQL server qu'en dernier recours.
Une façon de l'éviter est, en autre, de donner un maximum d'informations au "query optimizer".
Cela est possible:
  1. En complétant au maximum la requête SQL (plus de critères dans la clause WHERE, augmenter les critères de jointures dans les joints, etc).
  2. Réécrire la requête SQL différement (par exemple, remplacer les outer join par des sub-query).

SQL Server Training (Jour 4) - View et Stored Proc

Views
Les vues sont vraiment très populaire dans beaucoup de companies pour les raisons suivantes:
  • Les données sont publiées via une View sur laquelle on applique la sécurité. Un access direct aux data model n'est jamais fournit.
  • Les données sont modifiés à l'aide de stored proc (utilisation de sécurité EXECUTE).
  • Dans ce cas de figure, la view intervient comme une couche d'abstration masquant le Data Model sous-jacent. Il est dont possible de faire évoluer le schéma sans que cela perturbe les applications clientes en adaptant les views.
  • Permet d'organiser les données pour export (bien qu'il y ait d'autres outils pour cela).
  • Permet de nommer clairement (humainement compréhensible) les colonnes.
  • Permet de masquer les informations non pertinentes.
  • Par défaut, les enregistrements d'une view peuvent être mis-à-jour ou effacés (si la view n'est, bien entendu, pas trop compliqué. Voir 7-10).
Désavantages:

  • Il faut garder à l'esprit que les views diminuent les performances du moteur DB (parce que les noms sont évalués on-the-fly). Ainsi, on veillera à ne jamais dépasser 5 niveaux (View built on another view).
  • Eviter les jointures dans le views (après 5 jointures, les performances sont terriblement mauvaises).
SCHEMABINDING
Les views n'utilisent pas de contrainte fortes sur le schema (Par default, SCHEMABINDING n'est pas actif). Cela présent un avantage et un inconvénient.
L'avantage est qu'il est possible de modifier le schéma sous-jacent sans devoir effacer et recréer la view. C'est vraiment pratique pour les opérations de maintenance. Cependant, si erreur il y a (parce qu'il manque une colonne nécessaire dans la table sous-jacente), elle ne sera révélée que lorsque la view sera accédée.
Avec un SCHEMABINDING, il sera impossible de modifier les tables sous-jacentes sans détruire les views qui l'utilise (pour les recréer après).
Cela diminue certe le risque d'erreur mais rends la maintenance très contraignante.

Persistant Index
Comme précisé précédemment, les Views ne sont pas très performantes. C'est encore plus vrai si elles couvrent de grandes tables ou de multiple jointure.
L'une des façon de contourner ces problèmes de performances est d'utiliser une "persistant index" sur la view.
Cette opération d'indexation de view crée effectivement un CLUISTERED INDEX. C'est a dire un index B-TREE contenant les pages de données... comme il s'agit d'une vuew, c'est une copie des pages de donnée qui se retrouvent dans l'arbre.
Et bien entendu, ce sont toutes les données qui sont dupliquée. La view sera effectivement performante... mais il y a un prix (les données sont dupliquées).
Bien que couteuse, cette métode a un avantage indéniable. En cas de corruption de la table source, SQL Server sera capable de récupérer les données corrompues depuis le "persistant index" (avec DBCC DBRepair).  

Maintenance: Utilisation de view et Triggers
Si une table disparait du data-model pour être remplacé par une structure plus compliquée, il est possible de la "re-rendre disponible" via une View.
L'utilisation de TRIGGER INSTEAD OF permet même de continuer à supporter les operations insert/Update/Delete sur la view.

Stored Procedure
Pas grand chose de nouveau à apprendre dans ce domaine. Cependant, ce ne fût pas une perte de temps.

Il est fortement conseillé d'éviter l'usage des tables temporaires (#TempTableName) et des Curseurs lorsque cela est possible. L'utilisation de nouvelles structures et fonctionnalités de SQL Server permettent d'obtenir des codes 30 fois plus rapides.

Il ne faut JAMAIS utiliser le préfix "sp_" pour nommer les procédure. "sp_" est réservé aux "System Procedures". Lorsque l'interpreteur SQL essaye de résourde le nom de la stored proc commençant par "sp_" dans la master DB. Si elle n'y est pas retrouvée, une tentative de localisation dans la DB courante est alors entamée. Cela représente une surcharge d'exécution inutile!

Une stored procedure retourne toujours un entier. Cette fonctionnalité devrait être utilisée pour retourné un status d'éxécution à l'appellant. Par convention 0 = false, 1..N indique un status.
Le status est assigné avec avec l'instruction return (ex: RETURN 2).
Le status est récupèré lors de l'appel par une assignation directe.
Exemple:
DECLARE @UspStatus integer
DECLARE @AParam varchar(50)
SELECT @AParam = 'Hello'
DECLARE @MyResultingText varchar(100)
EXEC @UpsStatus = MyStoredProc "Param1", 5, @AParam, @MyResultingText OUTPUT

Recommandations
  • Préfixer les stored procedure avec "usp_" pour "User Stored Procedure" (recommandation).
  • Lors des appels de stored procedure, ne pas oublier d'utiliser le mot clé OUTPUT pour récupérer un paramètre par valeur (sinon NULL est retourné).
    EXECUTE @ProcStatus = ProcedureName ParameterValue, @ParameterVariable, @ReturnedValue OUTPUT
  • Une stored procédure doit toujours vérifier la validité de sess paramètres.
    IF (@Value <0 )
    RAISERROR( 'Error Message', 14, 1 )
    RETURN
    END
  • Lors d'un RAISERROR, ne pas utiliser des erreurs avec une trop grande sévérité car cela rompt la connection (avec des effets indésirés).
  • Utiliser la variable @@recordCount pour connaître le nombre de records retourné par la dernière opération SQL.
  • Lors de la modification d'une stored procédure, ajouter les nouveaux parametres avec une assignation de valeur par défaut. Cela permet aux applications existantes de continuer à fonctionner sans modification.
  • Lors de l'appel d'une stored procédure, utiliser le mot clé DEFAULT pour utiliser la valeur par défaut (signalée dans la définition dans la store procédure).
Plan d'éxécution des stored procedure
Le plan d'exécution permet d'avoir une synthèse des opérations effectuées par SQL Server durant l'exécution d'une requête SQL.
L'activation de l'EXECUTION PLAN depuis la console SQL est triviale (depuis la barre des boutons).
Cependant, lorsqu'il s'agit d'une stored procedure, il faut faire appel à des options spécifiques.
Il est ainsi possible de détecter les opérations couteuses dans une stored procedure afin de les optimiser.

Il y a différentes façons d'obtenir des informations d'exécution:

SET STATISTIC IO ON/OFF
Affiche dans les messages le nombre de pages de 8kb lues depuis le disque.
Logical Reads: # de pages qui devaient lues pour atteindre l'objectif.
Physical Reads: # de pages chargées depuis le disque (les autres pages se trouvaient dans le cache).
Read-Aheads: Lors d'operations avec temps de processing perdu, SQL serveur prend l'initiative de lire des pages complémentaires (# de pages chargées en plus dans le cache).

SET STATISTIC TIME ON/OFF
Affiche les details de temps d'exécution dans les messages.

SET STATISTICS PROFILE ON
Fonctionnalité très utile mais malheureusement disparue en SQL2008.
Fournit le plan d'exécution sous forme de table relationnelle.
Il y est possible de lire l'entièreté du schema d'execution presqu'aussi simplement que le graphique lui-même.

SET STATISTICS XML ON
Produit les même information que STATISTICS PROFILE au format XML.
Ce format à l'inconvenient d'être moins lisible et donc plus difficile à exploité par simple lecture. Cependant, il existe une foule de logiciel exploitant ce format pour en reconstituer un graphique.
Contient en autre un noeud nommé MissingIndexGroup.

vendredi 17 octobre 2008

SQL Server Training (Jour 3) - Intégrité et Trigger

Voila, je vais vite profiter d'une petite pause pour publier le résumé d'avant hier.
Je commence vraiment à crouler sous l'information :-)

Intégrité des données
Aujourd'hui cours sur la gestion de l'intégrité dans les DB.
Il y a trois façons de gérer l'intégrité:
  1. Domain Integrity: Contrainte sur les colonnes, restreindre les valeurs dans le colonnes.
  2. Entity Integrity: intégrité des enregistrements. Chaque record doit être identifié de façon unique (utilisation de Primary Key)
  3. Referential Integrity: L'information contenue dans une colonne doit correspondre au contenu d'une clé primaire d'une autre table.
Options pour renforcer l'intégrité des données:
  • Data types.
  • Rules:  utilisé pour définir les valeurs acceptables dans une colonne. (OBSOLETE, not Ansi compliant).
  • Default Values: permet de définir la valeur par défaut de certains champs. (OBSOLETE, not Ansi compliant).
  • Xml Schema: Permet de renforcer la validation des données dans les champs XML.
  • Triggers: Permet l'execution de code au moment de la sauvegarde/mise-à-jour/effacement d'enregistrement. Les triggers permettent un controle poussé de l'intégrité et du flux de donnée.
  • Constraints: Ansi compliant. Definit comment la moteur DB doit renforcer l'intégrité des données.
    Il existe plusieurs type de contraintes:

    1. Primary Key
    2. Default
    3. Check
    4. Unique - La valeur contenue dans la colonne (ou combinaison de colonnes) doit être unique pour toute la table.
    5. Foreign Key  
Limite des contraintes:
  1. Ne peut pas extraire des données depuis une autre table.
  2. Ne peut pas faire appel à une stored procedure.
Check Constraint
Cette contraite permet de faire des vérifications sur les données (sur base d'expression) lorsqu'elles sont modifiées.
Cette contrainte est l'une des plus mal estimée alors qu'elle est la plus simple et fournit l'une des plus grande valeur ajoutée.
Plusieurs Check Constraint peuvent exister sur un même champ.
Un Check Constraint peut faire référence à un autre champs de la table (mais pas à une autre table).
Les "Check Constraint" ne peuvent pas contenir de sous query (voir Trigger).
Avantages:
Permet la modification d'information depuis une application tiers (Access) ou l'administrateur (SQL Statement) sans mettre l'intégrité des données en danger.
Note:
Il est possible de désactiver des "Check Constraint" pour accélérer le traitement de longues opérations (update, reload).

Foreign Key Constraint
Cette contrainte permet de s'assurer que la valeur d'une colonne correspond bien au contenu de la clé primaire (unique) d'une autre table.
C'est une contrainte d'intégrité référentielle.
Pour un champs soumis à une foreign key, il est impossible d'y introduire une valeur illégale. Bien que protégeant bien l'intégrité des données, les Foreign Keys présentent quelques désavantages les rendant peu populaire.
C'est ainsi que beaucoup de sociétés préfère ne pas implémenter ce genre de contraintes en production (leur préférant les triggers).
Actions:
Lors de la définition des "Foreign Key" constrainte, il est possible de préciser une clause CASCADE (update or delete). Cette dernière clause permet d'indiquer quel operation doit être exécuté sur le record lorsque la référence est modifiée ou effacée.
Par default, l'action est NO ACTION dans les deux cas.
Il est possible d'utiliser CASCADE qui est vraiment dangereux lors de l'effacement de la référence car il efface également les dependences.
Si orderDetails.ProductID reference la table product avec DELETE Cascade, alors l'effacement d'un produit efface également toutes rows orderDetails (where orderDetails.ProductID=product.productID). OUPS!
Il existe également des options SET NULL ou SET DEFAULT (voir 5-21). 

Désavantages:
  • Limite les operations de modification de schéma (renommer des colonnes).
  • Consomme des ressources (il faut faire un choix entre performance et sécurité).
  • Peut se montrer lents lors que la clé primaire de référence appartient à une table très grande.
  • Nécessaire de désactiver ce type de contrainte lors du rebuild des indexes.
  • Représente des contraintes d'utilisation vraiment excessives pour les DB de reporting. Il est en effet courant d'effacer et de recharger de nouvelles données en masse dans ce genre de DB. Dans ce cas, les foreign key représentent des contraintes non nécessaire puisqu'il n'est pas possible de tronquer la table... et la mise à jour d'information en masse est fortement ralentie par la vérification de la contrainte.

Default Constraint
Vraiment utile pour s'assurer que certains champs soient tooujours correctement initialisés.
Sont utilisation est recommandée. 

Triggers
Les triggers permettent d'activer du code (actions) lors d'un événement d'insertion/update/delete de records sur une table.
Le trigger est appelé une seule fois par opération (quelque soit le scope de l'opération). Qu'une requête sql modifie ou efface 1 ou 2000 enregistrements (en fonction de sa where clause), le trigger ne sera activé qu'une seule fois pour la modification entière.
Les triggers sont toujours executés dans la même transaction que l'événement.
Il est par conséquent possible de faire un rollback pour annuler l'événement d'origine.
Mais en contre partie, il faut veiller à avoir un trigger aussi court que possible afin de limiter le temps de transaction.

Il y a deux type de triggers:
  1. After Trigger: Trigger qui sont exécutés après l'événement sur la table. Ce qui permet par exemple de vérifier des contraintes d'intégrité ou de maintenir des tables d'audit. 
  2. Instead Of Trigger: Trigger qui remplace l'événement. Ce qui permet de modifier le comportement standard de SQL Server. Eg: remplacer un effacement physique par un effacement logique ou encore répartir l'information au sauvegarder entre plusieurs tables (utile lorsque le trigger est placé sur une vue).
Recommandation d'usage:

  1. Récuperer les records insérés ou mis-à-jour depuis la table virtuelle "udpated".
  2. Récuperer les records effacés depuis la table virtuelle "deleted".
  3. Le trigger doit être écrit de façon fonctionner avec une table deleted et updated contenant plusieurs enregistrement (erreur courante).
  4. En cas d'effacement, toujours faire un count(*) from deteled pour s'assurer qu'il y a des informations à effacer.
  5. Par default, un trigger n'est pas récursif sur sa propre table.
  6. Un trigger peut déclencher un trigger sur un autre table (cascading firing)

Informations diverses:
  • Pour tester si un champ a été modifié, utiliser la fonction Update(FieldName)
  • Pour stopper une trigger (rollback), utilser RaiseError( N'Message', 10, 1 )
  • Lorsqu'un trigger insert des records dans une autre table, utiliser le mot clé OUTPUT pour récupérer les valeurs des champs identity dans une variable de type table (voir autre article à venir)

Cas d'utilisations:
  • Effectuer un effacement logique (active=0) lors d'une instruction DELETE FROM.
  • Eviter les effacements physique en les interdisants. Meme si la sécurité est mal configuré, il ne sera pas possible d'effacer les records.
  • Propagation d'état. Par exemple, la désactivation d'une catégorie de produit peut egalement désactiver tous les produits et ajouter un commentaire aux commandes en cours sur ces produits.
  • Permettre d'effectuer des vérifications complexes et de retourner des messages d'erreurs préçis.
  • Remplacement de Foreign Key constraint... car les trigger peuvent être désactivés et réactivé pour accélérer des opérations de maintenance. La contrainte d'intégrité implémenté dans le trigger ne sera revérifiée que lors d'une nouvelle modification de l'enregistrement.

jeudi 16 octobre 2008

SQL Server Training - Migration et compatility Level

Durant mon training, j'ai eu l'occasion de mettre la main sur une série de script de diagnostique SQL2005 plus que très intéressant (missing indexes, Index Fragmentation, Index usage, etc).
Ces scripts sont, bien évidement, exécutés depuis une console TSQL et fonctionnent comme attendu.

Par contre, certains d'entre-eux ne fonctionnaient absolument pas la DB de TrialXS.
Vraiment étrange si l'on sait que ces scripts n'analyse que des données système.


La réponse est simple... La DB TrialXS est restaurée depuis un backup SQL2000.
Par conséquent, le compatibility mode "SQL 2000" est appliqué à la DB (voir DB Options) sour SQL2005.
En modifiant le "compatibility mode" j'ai enfin réussit à tester mes merveilleux scripts.

Par contre cela lève une nouvelle question: 
Comment nos applications ISAPI (ou script de migration DB) vont-ils réagir en se connectant sur une même DB configurée en compatibility mode SQL7 (prod actuel) ou SQL2000 (ancien env. développement) ou SQL2005 (actuellement non activé)?


Pour des raisons évidentes de facilités de maintenance (à venir... mais avec les super trainings scripts SQL), les "compatibility mode" des DB de production doivent être configurés SQL2005.

mercredi 15 octobre 2008

SQL Server Training (Jour 2)

Que retenir de cette deuxième journée:

XML
Maintenant que SQL Serveur dispose d'un datatype natif XML, il est possible:
  1. De stocker du contenu XML dans un champs et d'y appliquer des méthodes de traitement spécifiques (XQuery).
  2. De générer directement du contenu XML depuis une requête SQL (FOR XML).
  3. D'accepter un input XML, de le parser et le transformer en données relationnelles (OPEN XML).
Ce chapitre fut relativement intéressant. Surtout concernant la génération de document XML directement depuis des requêtes sql.
Dans ce dernier cas, si l'output n'est pas trop conséquent, cela peut vraiment présenter un avantage. Dans le cas contraire, la mémoire cache et Execution Plan Cache seront pénalisés afins de pouvoir générer le document.
L'intégration de XQuery permet de faire des requêtes vraiment puissantes mixant traitement XML (sur du contenu XML d'un champ) et datatype SQL. Cependant, cela nécessite un parsing des documents XML row par row... ce qui est vraiment très pénalisant pour un moteur de DB.
A noter que la mise en place d'index XML primaire et secondaire (FOR PATH) permettent de réduire le temps de processing XML de façon significatif (D'un coût de 266 à 0.1).
Finallement, d'un avis tout personnel, je ne suis pas certain qu'il soit intelligent de stocker du contenu XML dans une DB en vue d'un traitement quelconque (surtout s'il est récurrent).
L'intégration de contenu XML n'est pas en concordance avec l'aspect d'exploitation relationnel de l'information. Par ailleurs, durant le training, nous n'avons pas fait la référence à un cas existant (même sur demande).

Définition des indexes
Nous avons également eu l'occasion de nous consacrer sur la gestion, la création et le l'optimisation des indexes.

Clustered Index:
Index dont les data pages sont stockées dans l'ordre physique de l'index.
L'index cluster est basé sur un arbre B-Tree BALANCE (équilibré autour du noeud root), chaque noeud disposant de relations "sibling" en plus des relations ascendantes et descendantes.
L'introduction d'un nouvel enregistrement dans de tel index est couteux car il faut eventuellement insérer des pages dans l'arbre, modifier les relations entre les différents noeuds... mais surtout garder l'arbre balancé.
L'avantage de cet index, est que SQL server maintien des statistique permettant d'évaluer la pertinance d'une recherche dans l'arbre (au lieu de simplement envisager un table-scan).

Non Clustered Index:
Fonctionne de façon identique au clustered index (B-Tree) A LA DIFFERENCE que les pages sont soit:
  1. Stockées dans la heap
  2. Soit déjà stockée dans un clustered index.
Chaque noeud du "Non Clustered Index" fait une référence à la page de donnée à l'aide d'une clé.

Note 1: Dans la cas d'une table ne disposant pas d'un Clustered Index, les pages sont stockées dans la heap. Il n'y a donc pas d'emplacement prédefinit pour créer de nouvelles les pages de données. Dans ce cas, les insertions sont plus rapides car la nouvelle page de donnée peut être placée arbitrairement.

Note 2: Dans le cas d'une table disposant d'un Clustered Index, pour accéder à l'information depuis un Non Cluster Index, SQL serveur doit faire beaucoup d'opérations en lecture.
A savoir:
  1. La lecture du Non Clustered Index pour récupérer 'identification des pages data (DataPageID)
  2. Parcours de l'arbre B-Tree pour localiser les pages (DataPageIDs) de données dans le Clustered Index. (il faut garder à l'esprit que dans ce cas, le clustered index n'est trié dans le même ordre).
Conditions de selection d'un index
  1. Pertinence de l'index.
    Un index est utilisé par SQL serveur s'il permet d'exclure 95% (au moins) des records de la table (lors d'une selection).
    Pour ce faire, SQL serveur consulte les statistiques d'index qui permettent d'évaluer la pertinance de l'index pour certaine valeur (Si la table contient 10.000 records et que la statistique mentionne un range de 2.500 records pour une selection particulière alors l'index sera rejeter... un table scan sera plus performant ).
    Il est également important de savoir que lors d'index sur plusieurs colonnes, seul les statistiques de la première colonne de l'indexe sont utilisées.
    Par conséquent, la sélection d'un index couvrant plusieurs colonnes ne se fait que sur base de la pertinance de la première colonne de celui-ci.
  2. Couverture de l'index.
  3. Ordre de tri.
  4. Les hints inclus dans les requêtes SQL pour modifier le comportement du moteur DB.
Gestion des indexes

En SQL2005 Enterprise, il est possible de faire des mise-à-jours d'indexes à la'ide de l'option WITH (ONLINE=ON). Cela évite de locker la table durant toute l'opération permattant ainsi aux applications de poursuivre leurs traitement sans interruption. Cette opération consomme néanmoins beaucoup de temps et de ressources.
Il est a noter qu'en SQL2000, le création d'un index place un Lock exclusif sur la table. Il ne faut donc jamais créer d'index sur les DB de production durant les heures de bureau.


En SQL2005, il est possible:
  1. De modifier (ALTER) ou de reconstuire (REBUILD) un index. Sous SQL2000, la seule option est de détruire et recréer l'index.
  2. d'indiquer le nbre maximum de processeur affecté à la modification d'un index. WITH( MAXDOP=3)
  3. Il est possible de definir une granularité de locking plus fine sur les indexes (ALLOW_ROW_LOCKS). Par default le moteur SQL utilise des locks au niveau de la table!!!. 
  4. D'inclure des colonnes dans l'index sans que ces dernières n'interviennent dans l'index lui-même. Cette dernière optimisation permet de tirer parti des index sur colonnes multiples sans en avoir les inconvénients. En général, les colonnes additionnelles sont ajoutées pour retrouver rapidement des information pertinantes depuis l'index sans lecture de data pages complémentaire. Avant SQL2005, ces colonnes faisaient partie intégrante de l'index... par conséquent, toute modification des colonnes complémentaires réclamaient la mise-à-jour des liens internes et une opération de re-balancing... alors même que ces informations ne participent pas activement à l'index... c'était donc des indexes couteux.

    Avec les "Included Columns", la modification des données complémentaires  n'implique pas les opérations de mise à jours de liens internes et de re-balancing.

    Les indexes en SQL2005 sont à ce point plus efficaces qu'il est possible d'éliminer jusqu'à 60% des indexes nécessaires en SQL2000 tout en gardant les mêmes performances

  5. De créer des "Partitionned index" fonctionnant de façon similaire aux tables partitionnées.
  6. D'indexer le contenu de champs XML afin d'améliorer les performances et cout de recherche de façon spectaculaire.
  7. De désactiver/réactiver des indexes lors de l'exécution de gros batch. Cela permet de gagner du temps machine considérable en évitant à SQL server de constamment mettre à jour l'index. Lors de la réactivation de l'index, ce dernier est reconstruit.
Optimisation des indexes

Database Engine Tuning Advisor:
Cet outil de Microsoft est maintenant bien peaufiner et est un incontournable pour l'optimisation des indexes.
Afin d'effectuer une évaluation des indexes, le Database Engine Tuning Advisor utilise une série de requêtes SQL sensées représenter les cas d'utilisations pratique de la base de données. Ces informations peuvent être fournie depuis un fichier SQL, XML ou une trace collectée à l'aide du profiler SQL.
Malheureusement, ce cas de figure peut difficilement s'appliquer aux DB de production.

Exploiter les statistiques des DB:
Pour les DB de production, il faut savoir que SQL Serveur maintien des vues dynamiques reprenant les statistiques d'usage des différents indexes (dm_db_index_usage_stats).
Par ailleurs, le processus de plannification d'execution tiens des statistiques utiles à propos des indexes idéals répondant à certaines requêtes (dm_db_missing_index_details). Cette vue est utilisée par SQL Serveur lui-même pour éviter certaines conception de plan d'exécution inutiles.
Ces informations peuvent être exploitées avec IndexTuning.sql faisant des jointures sur sys.Indexes pour obtenir de précieux conseils... même en production.
From the result of indexTuning.sql, high cumulated_cost_reduction must be addressed!

Fragmentation des indexes:
Il existe deux types de fragmentations.
La fragmentation interne est due à SQL server lui même et nous ne pouvons rien y faire. Elle a d'ailleurs peu d'influence.
Par contre, la Fragmentation externe correspond à la distribution des pages de données sur le disque (espaces disques alloués par le système d'exploitation).
L'identification de la fragmentation se fait à l'aide de Fragmentation.sql (fichier de démonstration du module 4).
Pour une fragmentation inférieure à 30%, un simple ALTER INDEX ... REORGANIZE est suffisant.
Par contre, pour une fragmentation supérieur à 30% un ALTER INDEX.... REBUILD est absolument nécessaire. Cette dernière opération (couteuse) demande au système d'exploitation d'allouer un espace continu.