Un aspect souvent mal perçu entraînant une dégradation des performances réside dans la conversion implicite des données. Voici une petite démonstration de la chose, qui montre que malgré un index sur la bonne colonne, les performances peuvent parfois ne pas correspondre à celles attendues.
Le tableau ci-dessous (extrait de l’aide en ligne de SQL Server, https://docs.microsoft.com/fr-fr/sql/t-sql/functions/cast-and-convert-transact-sql) montre les différentes conversions explicites et implicites entre types de données sous SQL Server.
Nous nous appuierons ici sur la conversion entre le type int et varchar.
Créons une table contenant par exemple une liste de clients.
use tempdb go create table Clients (Id_Technique int identity primary key, Code_Client varchar(50), Nom_Client varchar(100), Date_Creation datetime) go declare @i int=0 while @i<100000 begin select @i+=1 insert into Clients (Code_Client, Nom_Client, Date_Creation) select @i, 'Client N°' + convert(varchar,@i), getdate() end
Parmi les 10 000 clients que nous avons insérés dans la table, cherchons par exemple celui dont le code est 1234.
select * from Clients where Code_Client=1234
Cela semble très bien, mais en regardant le plan d’exécution, on remarque que le moteur de données est obligé de parcourir toute la table à la recherche du bon client.
Du point de vue des ressources consommées, on obtient 568 lectures logiques pour trouver notre enregistrement, c’est-à-dire 568 pages de 8Ko ! C’est tout de même un peu exagéré pour une recherche qui parait très basique.
Réponse immédiate : mettons un index sur la colonne Code_Client, et ça devrait (a priori) mieux fonctionner.
create index IX_Code_Client on Clients(Code_Client)
Et maintenant, ça donne quoi ?
Ca a l’air un peu mieux, on passe par le fameux nouvel index, mais on se retrouve encore avec 239 lectures, dues à un parcours complet de notre liste de codes client au lieu de justement utiliser pleinement l’index pour trouver très rapidement le numéro exact demandé. Que s’est-il passé ?
La solution apparait en regardant de plus prêt les détails de cet Index Scan.
On y voit une conversion implicite. Qu’est-ce que c’est que cette bête ? Et bien, tout simplement, notre code client est stocké sous forme de chaîne de caractères (varchar(50)), et nous recherchons un code client exprimé sous forme numérique. Dans ce cas, le moteur effectue la conversion sous forme numérique, et doit donc convertir sous forme numérique chacun des codes clients qui se présentent à lui.
On arrive donc à la solution du problème pour enfin optimiser cette fichue requête :
select * from Clients where Code_Client='1234'
Nous obtenons enfin un joli Index Seek, qui nous donne au final un requête ne coûtant que 4 lectures logiques, c’est-à-dire seulement 32Ko.
Accessoirement, un autre cas particuliers aurait pu nous obliger tout simplement à exprimer correctement le code client recherché (c’est-à-dire sous forme de type de données correspondant à celui de la colonne utilisée pour le stockage…) :
Mais quand on fait quelque chose par obligation pour se débloquer, c’est toujours moins intéressant que d’avoir quelque chose qui marche tant bien que mal et que l’on peut prendre le temps de chercher à optimiser…