Catégories

Bonnes pratiques et surveillance de la performance d’un serveur SQL

Les serveurs SQL doivent faire l’objet de toute les attentions de l’installation jusqu’au paramétrage en passant par la mise en production. Je vais aborder les bonnes pratiques pour obtenir un service Microsoft SQL performant mais quels sont les compteurs importants pour surveiller les performances ou les benchmarker.

Notez bien que je ne suis pas un expert SQL, mais je pense que les méthodes décrites ci-dessous doivent être mises en oeuvre et considérées comme des bonnes pratiques. Si vous êtes expert SQL, n’hésitez pas à me remonter vos expériences et éventuelles omissions de ma part…

Stockage et les I/O

L’élément clé qui va impacter directement les performances d’un base de données transactionnelle est la notion d’IOPS (Entrées/sorties par seconde, le ratio associé, …), le débit n’étant absolument pas un critère de performance, mais une analyse des compteurs suivants seront déterminants: Moyenne lecture/écriture bytes/s, lecture/écriture par seconde, Lecture/écriture disque bytes/s, Moyenne disque lecture/écriture par seconde et enfin Moyenne disque de la file d’attente. Voici quelques Pattern I/O typiques:

  • OLTP (Online Transaction Processing) => lectures/écritures aléatoires intensives entre 8k et 64k – le plus souvent read-ahead – IOPS prépondérant
  • RDW (Relational Data Warehousing) => lectures séquentielles sur 64k et au-delà – écritures séquentielles sur 128-256k – débit prépondérant
  • Journaux => I/O séquentiels intensifs en écriture – latence prépondérante
  • Analysis Services => lectures sur 64k aléatoires
  • Ou alors le reste ;-) (Mixed)

Il convient donc de correctement dimensionner votre système (pas de sur-dimensionnement et encore moins de sous-dimensionnement) qui sera capable d’atteindre vos attentes en termes d’I/O mais aussi de latence (généralement entre 5 et 20 ms) tout en prévoyant la croissance des données. En premier lieu, les placements des différents composants SQL sur des piles RAID distinctes est essentiel, à savoir:

tempDB RAID 0 (1 -10) – disque SAS ou FC voire SSD
Journaux de transactions RAID 1 (10) – disque SAS ou FC voire SSD
Base de données RAID 5 (50-60) – disque SAS ou FC
Copie Secondaire – Dump – … RAID 5 – disque SATA

La règle veut que s’il n’est pas possible de répartir sur plusieurs piles RAID distinctes (physiquement différentes), il convient de regrouper sur la même pile les bases ayant le même profile I/O (Pattern I/O).

Plusieurs outils permettent de benchmarker votre serveur SQL afin d’en déterminer l’empreinte (Pattern I/O) pour ensuite pourvoir dimensionner sereinement sont stockage. Les outils permettant de connaitre les performances et/ou limites d’un stockage sont SQLIO et IOMETER (voir mon article sur le formatage des résultats). Un outil comme SQLIOSim permet de simuler un type de Pattern I/O pour analyser le comportement du serveur SQL/stockage, la nuance est importante !

Alignez vos partitions

Déjà abordé dans un précédent billet, l’alignement des partitions est un facteur important de performance souvent négligé. Si les pistes ne sont pas alignées avec les partitions, une opération d’E/S peut s’étendre sur deux pistes, ce qui entraîne une altération des performances, jusqu’à 25% de perte. Bref, il est impératif de le faire POST-INSTALLATION car l’alignement ne peut pas être modifié ultérieurement sans perte de données.Historiquement, la taille du secteur a été fixé à 512 octets. Les nouveaux lecteurs peuvent offrir des secteurs de 1 Ko, 2 Ko ou 4 Ko. La plupart d’entre nous appellent l’unité d’allocation par un autre nom: le cluster. La taille du cluster est déterminée lorsque la partition est formatée par le système d’exploitation. Par exemple, si les secteurs d’un disque dur de 512 octets (soit une décalage de 32,256 octets (63 secteurs*512 octets), soit exactement 31,5 KB), un cluster de 4 Ko dispose de 8 secteurs, et un cluster de 64 Ko a 128 secteurs. Il peut être donc légitime de formater avec un alignement à 32 Ko soit 32,768 octets. Bien souvent, les fournisseurs prennent les 63 premiers secteurs (cachés).

Windows Server 2008 formate par défaut avec un alignement à 1024 Ko soit 1.048.576 octets, tandis que les versions précédentes réservaient automatiquement 63 Ko et la partition venait « se coller » directement après. Cette valeur fournit une solution pérenne (du fait des réservation de secteurs par certains fournisseurs de hardware) et adaptée à des tailles de 64 Ko, 128 Ko, ou encore 256 KB voire même (rarement usité) 512 Ko et 1024 Ko.

L’image ci-dessous représente se base sur une taille de cluster de 4 ko et met en avant deux cas de figures: alignement (4eme ligne) et non alignement (3eme ligne). Le non-alignement met en évidence que la partition étant collée directement après le secteur 63, il reste 1 secteur de 512 octets vide sur un stripe (de la pile RAID ndlr) d’où un décalage des écritures, à savoir qu’une opération E/S requiert plusieurs E/S. Par exemple, 8 opérations E/S d’une taille de secteur de 8 Ko reviendrait en fait à 10 opérations E/S à cause du misalignement (soit 20% de perte de performance).

Même exemple, mais avec une taille de cluster définie à 64 Ko.

Concernant le formatage NTFS de vos partitions, Microsoft recommande une taille d’allocation de bloc d’une valeur de 64k aussi bien pour la partition hébergeant tempDB, les journaux et les bases.

Profondeur de file d’attente de vos HBA (Queue Depth)

Ce paramètre important et souvent négligé désigne combien de commandes bloc vont être envoyés simultanément. Un paramétrage trop petit va restreindre, étouffer les performances et augmenter la latence car le stockage va passer son temps a envoyer pour une opération de lecture de table par exemple de multiples commandes alors qu’une seule aurait probablement suffit. Par exemple pour un paramètre trop faible, pour lire un table 10 commande blocs vont être envoyées, un paramétrage affiné n’enverra que 2 commandes pour la même opération ! Par défaut, et généralement, le paramètre est de 32 sur les HBA; Microsoft recommande au moins 64 mais au delà il faut benchmarker, car ce site a démontré que en passant d’un paramètre de 64 à 128 on perds 90 I/O. En effet, un paramétrage trop grand génère également de la latence car le stockage va attendre que la file d’attente soit remplie pour l’exécuter…

Les pilotes sont également importants, il convient de voir avec les constructeurs s’ils ont de recommandations à ce sujet, Storport doit être préféré dans le plupart des cas (obligatoire en x64 car c’est le seul supporté) à SCSIport. Pour rappel, le premier accepte une valeur maximale de 255 I/O par LUN tandis que le dernier (SCSIport) est de 255 pour la HBA… Le multipathing MPIO optimal est l mode Round-Robin. Je rappelle également qu’utiliser 2 HBA (FC ou iSCSI) distinctes permet de répartir la charge sur l’ensemble de l’architecture PCI et si possible de dédier les ports à SQL.

Il convient de monitorer la latence, la file d’attente actuelle (Current Disk Queue) doit être inférieure à 2 (3 au maximum) soit une valeur de 54 pour 23 disques => 54/23 = 2.34, attention donc ET les transferts disques/s doivent être inférieurs à 0.3.

Un benchmark a démontré qu’une Queue Depth à 32 délivre 48 IO tandis qu’à 64, on atteint 162 I/O !

Les FILEGROUPS

Pour rappel, SQL génère trois types de fichiers différents: les données primaires MDF, secondaire NDF et les logs LDF. La fonctionnalité FILEGROUP permet de regrouper des données pour des raisons d’administration mais aussi de performances (voir plus bas). A noter que les journaux de transactions ne font jamais partis d’un FILEGROUP. Dans l’exemple ci-dessous une base MaBase est crée avec deux fichiers dans un FILEGROUP MaBase_FG_2 et pour terminer on définit ce FILEGROUP comme étant par DEFAULT.


CREATE DATABASE [MaBase] ON  PRIMARY
( NAME = 'MaBase', FILENAME = 'D:\MSSQL\DATA\MaBase.mdf' , SIZE = 4096KB , FILEGROWTH = 1024KB ),
FILEGROUP [MaBase_FG_2]

( NAME = 'MaBase_2', FILENAME = 'D:\MSSQL\DATA\MaBase_2.ndf' , SIZE = 4096, FILEGROWTH = 1024KB ),

( NAME = 'MaBase_3', FILENAME = 'D:\MSSQL\DATA\MaBase_3.ndf' , SIZE = 4096, FILEGROWTH = 1024KB )
LOG ON
( NAME = 'MaBase_journaux', FILENAME = 'E:\MSSQL\DATA\MaBase_journaux.ldf' , SIZE = 2048, FILEGROWTH = 10%)
GO
ALTER DATABASE MaBase
MODIFY FILEGROUP MaBase_FG_2 DEFAULT

Ou encore pour ajouter un fichier à un FILEGROUP:

ALTER DATABASE MaBase
ADD FILE (NAME = MaBase_4,   FILENAME = 'D:\MSSQL\DATA\MaBase_4.ndf')
TO FILEGROUP PRIMARY;
GO

L’avantage permet d’étendre une base sur d’autre piles RAID/disques et donc, de pouvoir gérer un manque de place par l’ajout de stockage mais aussi de répartir les écritures sur plusieurs stockage d’une même base, de plus SQL équilibre l’ensemble des lectures/écritures sur un FILEGROUP ! Par exemple il est ainsi possible de place une table très sollicité sur un RAID-10 et les autres sur un RAID-5 ou séparer les tables des index. L’intérêt des stockages utilisant la fonctionnalité AUTO-TIERING est remarquable pour ce type d’application, il convient néanmoins de s’assurer du bloc minimal pris en charge par l’algorithme, à 5 Mo il ne servira à rien !

L’idée des FILEGROUP est de répartir les données sur plusieurs FILEGROUP placés sur des stockage distincts (deux partitions sur une même LUN ne sert à rien…) afin d’accroitre les performances. Ainsi pour une table répartie sur 4 FILEGROUPS, SQL utilisera 4 threads pour accéder à la table, soit 1 par FILEGROUP qui bien sont placés sur des piles RAID distinctes, d’où l’obtention d’excellentes performances !

  • Il est recommandé de mettre de .25 à 1 fichier par FILEGROUP par CPU
  • RECOMMANDE pour la base tempDB d’avoir 1 fichier par CPU
  • Tous les fichierrs d’un même FILEGROUP doivent avoir la même taille
  • Un processeur quadri-coeurs compte comme 4 CPU, l’Hyperthreading ne compte PAS
  • Si le compteur File D’attente Disque est supérieur à 3, réduisez le nombre de fichier par disque

Vous trouverez ici comment manipuler les FILEGROUP et ici une discussion intéressante sur la ratio FILEGROUP par CPU.

NUMA

Depuis SQL Server 2005 (et SQL Server 2000 SP4 , avec limitations), la prise en charge de NUMA (soft-NUMA ou NUMA dans le hardware) est effective. Beaucoup d’encre a coulée à ce sujet, et je vous recommande la lecture de plusieurs sites à ce sujet.

La requête suivante permet de savoir si NUMA est utilisé de façon matérielle ou non.

SELECT DISTINCT memory_node_id
FROM sys.dm_os_memory_clerks

Ces sites vous permettront de vous documenter à propos de NUMA:

Voici les sites que je vous recommande de lire pour approfondir vos connaissances:

Quelques astuces

  • Formatez toujours votre stockage en NTFS en rapide et créer vos bases en Instant File Initialization
  • La fonction AUTOGROW peut/doit être laissée active (pour des raisons de sécurité) à condition de suivre l’évolution de vos bases !
  • Pré-définissez la taille de vos bases et des jounaux (environ 20 à 30% de la taille d’une base)
  • Définissez une taille maximale pour ne pas excéder le stockage en place au détriment d’une autre base
  • Votre strize size doit être de 64 ou 256k
  • Activez le Page Checksum – allez chez le MVP Christian Robert pour en savoir plus.

Les compteurs de performances

Le stockage

Les performances d’un stockage se mesurent à l’aide des indicateurs suivants: (référence Microsoft http://msdn.microsoft.com/en-us/library/ms191246.aspx)

  • Moyenne des écritures et lectures disque par seconde (Average Disk Sec/Read et Write) => mesure les temps de réponses
  • Lecture/écriture disque, octets/s (Disk Read/write Bytes/s) => mesure le débit (throughput) et permet ainsi de savoir si on sature une interface PCI-e, par exemple => IOPS
  • Transferts par seconde => permet de savoir si une application et/ou son Pattern I/O génère plus de requêtes I/O que ne peut supporter le stockage
  • Lectures et écritures par seconde => permet de déterminer le Pattern I/O
  • Moyenne disque, octects/lecture & écriture (Average Disk bytes/read & write) => définit la taille des I/O
  • Longueur moyenne de file d’attente (Average Disk Queue Length) => mesure les opérations disques en attente (2 par disque)
  • Inactivité en % (% Idle Time) => mesure l’activité disque
  • I/O partagées => mesure s’il faut plus d’une (1) commande pour traiter une I/O
  • Taille de file d’attente du disque actuelle (Current Disk queue Length) => mesure les I/O en attente

Des temps de réponses élevés (Average Disk Sec/Read et Write – valeur supérieure à 15 ms) ou des I/O trop importants (Disk Transfers/s – IOPS au délà de ceux admis par le disque ou la pile RAID) sont généralement provoqués par un non-alignement des partitions.

Un débit faible (Transfers/s) mais un compteur Disk Bytes/s élevé indique une possible fragmentation du stockage (valeur I/O partagées ou Split I/O) du fait qu’une simple requête est divisée en plusieurs.Un nombre insuffisant de disque dans un pile RAID peut être détecté si la valeur Disk Queue Length est supérieure à 2 voire 3 dans certains cas (disque SAS ou FC – 10 ou 15k).

A noter également qu’une longueur de file importante et une latence faible indique que la file se vide et se rempli très vite, et que par conséquent la système est efficace ! (tout ça pour dire qu’une file importante n’est pas FORCEMENT un problème à part si la latence est élevée !)

Disque\Moyenne des écritures et lectures disque par seconde < .0.005 soit 5 ms = excellent

5 à 10 ms = bon

10 à 15 ms = acceptable

> 15 ms = problème

Logs: 1 à 5 ms

Base OLTP: 5 à 20 ms – 10 recommandé

Base RDW: 25 à 30 ms – 10 recommandé

La mémoire

Les problèmes mémoire souvent causé par une insuffisance, une fuite mémoire, ou des commutateurs inadéquats (/3GB). Voici les compteurs à prendre en compte pour une analyse

  • % d’octets dédiés utilisés (% Committed in use) => mesure la mémoire utilisé
  • Entrés libres en table des pages systèmes => mesure le nombre de pages NON utilisées par le système
  • Pages par seconde => mesure les pages sont utilisés pour corriger des page faults

Les fuites mémoires sont repérables grâce aux deux derniers compteurs, à savoir une valeur inférieure à 5000 pour le premier compteur, et une valeur supérieure à 1000 pour le second. L’ajout de mémoire doit être opéré si le premier compteur renvoi une valeur supérieure à 80%.

Le processeur

Les compteurs suivants indiquent une saturation du processeur, à savoir:

  • % temps processeur => une valeur supérieure à 85/90% indique que le processeur est saturé
  • Longueur de la file processeur => une valeur supérieure au double des CPUs installés indique une saturation – exemple un quadri-coeur: 4*2=12 étant la valeur maximale

Le réseau

Les compteurs suivants permettent de mesurer un réseau, à savoir:

  • Total des octets/s (Bytes Total/sec) => indique de débit (voici la formule de calcul: paquets/sec * 1500 * 8 / 1 000 000)
  • Longueur de la file d’attente de sortie (Ouput Queue Length) => mesure la longueur d’une file en paquet. Une valeur supérieure à 2 indique une saturation

La formule suivante indique une saturation de l’interface: Total des octets/s / bande passante actuelle > 0.6

SQL Server

Les compteurs suivants permettent de mesurer la performance d’un serveur SQL:

  • SQL Access Method\Pages Splits/s => mesure le nombre de pages partagées (dû à un index plein)=> doit être inférieur à 100
  • SQL Statistics\Batch Requests/s => mesure l’activité globale du service SQL => une carte Gigabit supporte en 30000 !
  • SQL Buffer Manager\Lazy Writers/s => mesure le nombre de pages « dirty » écrites sur le disque => idéalement, la valeur doit être le plus proche de zéro avec un maximum de 20/25
  • SQL Buffer Manager\Page Life Expectancy => mesure la durée de vie d’une page dans le buffer => la valeur doit être inférieure à 300 secondes

Plusieurs documents sont à imprimer et à garder sous la main, ils récapitulent en détail les compteurs essentiels a surveiller. A télécharger dans l’ordre ici - ici et ici. Et en bonus, une vidéo ;-)

Les Dynamic Management Views – DMV

Les fonctions et vues de gestion dynamique renvoient des informations sur l’état du serveur, qu’il est possible d’utiliser pour surveiller l’état d’une instance du serveur, diagnostiquer des problèmes et régler les performances.

La DMV sys.dm_exec_query_stats fournit des statistiques de performances agrégées pour les plans de requête mis en cache, notamment des détails sur les lectures/écritures physiques et logiques et le nombre de fois que la requête a été exécutée. Il est ainsi possible de connaitre les requêtes les plus coûteuses en I/O ou encore en CPU, par exemple.

SELECT TOP 10
[Average CPU used] = total_worker_time / qs.execution_count
,[Total CPU used] = total_worker_time
,[Execution count] = qs.execution_count
,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2,
(CASE WHEN qs.statement_end_offset = -1
THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2
ELSE qs.statement_end_offset END -
qs.statement_start_offset)/2)
,[Parent Query] = qt.text
,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY [Average CPU used] DESC;

Autre exemple affichant les informations aux I/O et leurs tailles.

SELECT db_name(database_id) AS Database_Name
, file_id
,CAST(num_of_reads AS BIGINT) AS [total_num_reads]
,CAST(num_of_writes AS BIGINT) AS [total_num_writes]
,CAST(io_stall_read_ms AS BIGINT)
/ CAST(CASE WHEN num_of_reads=0

THEN 1
ELSE num_of_reads
END AS BIGINT) AS [avg_read_stall]

,CAST(io_stall_write_ms AS BIGINT)
/ CAST(CASE WHEN num_of_writes=0

THEN 1
ELSE num_of_writes
END AS BIGINT) AS [avg_write_stall]

,CAST(num_of_bytes_read AS BIGINT) AS [total_bytes_read]
,CAST(num_of_bytes_written AS BIGINT) AS [total_bytes_written]
,CAST(num_of_bytes_read AS BIGINT)
/ CAST(CASE WHEN num_of_reads=0

THEN 1
ELSE num_of_reads
END AS BIGINT)

/ 1024 AS [avg_read_size_Kbytes]
,CAST(num_of_bytes_written AS BIGINT)

/ CAST(CASE WHEN num_of_writes=0
THEN 1
ELSE num_of_writes
END AS BIGINT)

/ 1024 AS [avg_write_size_Kbytes]
FROM sys.dm_io_virtual_file_stats(NULL,NULL)

Le DMV sys.dm_os_performance_counters affiche des compteur SQL par l’intermédiaire d’une requête. Dans l’exemple ci-dessous, un reporting des logins/s :

SELECT valeur
FROM sys.dm_os_performance_counters
WHERE OBJECT_NAME = 'serveur-sql'
AND counter_name = 'Logins/sec'

La commande suivante permet de retourner tous les compteurs disponibles:

SELECT *
FROM sys.dm_os_performance_counters;
GO

Quelques exemples de diagnostics

  • Fragmentation: la DMV sys.dm_db_index_physical_stats retourne un pourcentage de fragmentation avg_fragmentation_in_percent qui ne doit pas excéder 25%
  • Processeur: si la DMV sys.dm_os_wait_stats renvoi une valeur élevée, le processeur sature
  • Engorgement des journaux de transactions: la DMV dm_os_wait_stats retourne des valeurs élevées parmi les compteurs WRITELOG et LOGBUFFER
  • etc….

Bref, je vous recommande les lectures dans sites suivants:

La mémoire cache des baies SAN

Beaucoup d’idées quant à la mémoire cache des baies de stockage, mais voici les principales règles:

  • Le cache en écriture doit être activé car il permet de maintenir une latence faible et d’absorber d’éventuels pics (bursts)
  • Le cache en lecture n’est que peu utilisé, si votre baie dispose d’un paramètre PREFETCH, activez-le, il s’avéra utile si un flux séquentiel est détecté. Un cache de type READ-AHEAD (lecture anticipée) ne sert à rien du fait que SQL utilise sont propre algorithme
  • Un règle 80/20 ou 90/10 coule donc de source
  • Afin de préserver l’intégrité des données, une batterie est obligatoire !

Ce document permettra d’en savoir plus à ce sujet.

Considérations spécifiques à Hyper-V

Outre le fait de me faire un peu de publicité quant à mon livre qui traite le sujet en profondeur, la planification de Microsoft SQL en environnement de virtualisation nécessite quelques bonnes pratiques:

  • Le disques doivent être de préférence en PASS-THROUGH et marquer offline au niveau de la VM
  • Le cas échéant, préférez des disques de taille fixe plutôt que dynamique (qui génère plus d’accès aux metadonnées et il résulte un nombre d’I/O plus important et un overhead CPU)
  • Les périphériques en mode synthetic
  • Les disques avec un contrôleur SCSI
  • Evitez d’affecter plus de 4 CPU à une VM ou de la virtualiser….
  • Tenez compte de l’overhead mémoire sur la partition parent (host) => 32 Mo jusqu’au premier Go puis 8 Mo par Go – une VM ayant 4 Go = 32 + 8*3 = 56 Mo (minime voire ridicule quant au regard du v-Index qui recense un ratio de 5:1 VM par serveur physique) => tout en compte, bien sûr, que Microsoft préconise 300 Mo pour l’hyperviseur et 512 Mo pour la partition parent
  • Activez pour vos cartes réseaux la fonction Chimney offload et Virtual Machine Queues (VMQ)

Le débat revient souvent quant aux avantages et inconvénients d’utiliser un VHD ou un disque en direct (PASS-THROUGH), et d’après ces benchmarks, les différences sont minimes, un peu comme chez VMware qui avait réalisé ce test.

Voici deux liens permettant d’aller plus loin dans votre documentation, ici et ici.

Benchmarker avec SQLIO

http://tutorials.sqlserverpedia.com/SQLServerPedia-20090413-SQLIO.flv

Voici pour exemple un test SLQIO qui va mesurer les écritures aléatoires avec des I/O de 64k en utilisant 2 threads pendant 120 secondes sur la lettre M.


sqlio -kW -t2 -s120 -dM -frandom -b64 (-LS: mesure la latence sans mesurer les I/O et le débit) test.txt

L’équipe de Quest met à disposition un script excellent pour formater tout ça, et pleins de vidéos sous forme « tutoriel » sont également disponibles.

Simuler une charge avec SQLIOsim

L’outil SQLIOsim (anciennement SQLIOstress) effectue des tests d’intégrité et de fiabilité sur des sous-systèmes de disque. Ces tests simulent en lecture, écriture, checkpoint, sauvegarde, tri et les activités de lecture anticipée. Il indique même les soucis rencontrés pendant le benchmark.

Pour allez encore plus loin, il existe un outil (SQLIOsimParser) pour « PARSER » les résultats obtenus et permet même un export au format CSV.

Pour terminer…

Des ressources intéressantes, l’une provient de la TEAM SQLCAT, l’autre recense les 30 mythes de SQL et un site dans le même esprit.

image_pdfimage_print

7 réponses à to “Bonnes pratiques et surveillance de la performance d’un serveur SQL”

  • Bonjour et merci pour cet article très complet et très bien argumenté.
    Marc

  • Bonjour Cédric,
    Beaucoup de choses dans ce que tu mets ici. Quelques imprécisions plutôt que des erreurs : par exemple, pour les fichiers de la base de données TempDB, il est conseillé d’en avoir un par CPU de préférence sur des LUN séparés mais il est conseillé de se limiter à 8.
    En fait, la question est de savoir quel est la charge prévisible par rapport au serveur de base de données : la majorité sont des « petites » bases de données et tout ce que tu indiques ici n’est pas utile. Par contre, pour les systèmes dont les performances sont critiques, je suis d’accord à 100%. Et quand nous arrivons à ces besoins, il est important de se questionner sur des appliances SQL Server dont les performances sont garanties par le consturcteur (toutes les bests practices sont appliquées et le tuning est fait au plus prêt des meileures performances possibles.
    Donc, si je résume, le mieux de prendre conseil auprès de son expert SQL Server préféré…
    Cordialement,
    Philippe

  • Superbe tutoriel on m’avait déjà parlé de cette histoire mais pas avec autant d’option. Merci beaucoup !

  • avatar Tony:

    Tutoriel vraiment complet et bien travaillé. Il possède également de nombreuses références externes pour vraiment bien gérer l’administration d’un serveur SQL. Je garde cet article sous la main.
    Encore merci.

  • Bonjour cedric,

    Super informations sur SQL
    Merci pour ton travail et ton partage du savoir.
    Je viens de commander ton livre…
    j’espère trouver encore pleins d’info pointu….

    Cordialement,

Laisser un commentaire


7 − quatre =