mai
2012
Le terme anglais « SARGABLE » indique si une expression de filtrage (prédicat) peut utiliser ou non une recherche dans un index. Si c’est le cas, le prédicat est dit sargable, l’index est utilisé pour une recherche et le temps de réponse sera excellent. Sinon, le temps de réponse sera mauvais car il faudra balayer toutes les lignes de la table pour satisfaire la dempande… Mais quelles sont les expressions « sargable », peut t-on transformer une expression non sargable en expression sargable ? Voici quelques questions et les réponses associées, avec des exemples sous MS SQL Server…
Le terme « SARGABLE » vient de la contraction de l’expression anglaise « Search ARGument Able » c’est à dire « capable d’utiliser un argument de recherche ».
1 – RÈGLE GÉNÉRALE
Sont sargable :
les recherches qui portent sur le même sens tri que celui effectué pour la structuration de l’index (alphabétique pour des chaînes de caractères, numérique pour des nombres, temporels pour des dates…).
Ne sont pas sargable :
Le NOT n’est en principe jamais sargable, tout comme le OR et le IN avec plusieurs valeurs.
De même une colonne à laquelle on applique une opération, tout comme une colonne « noyée » dans une fonction n’est en principe jamais sargable. À ce sujet, méfiez vous des transtypages implicites !
2 – DÉTAILS
Nous disposons d’une table avec les colonnes suivantes :
et des index suivants :
X1 (colonne)
X2 (colonne1, colonne2)
Sont sargable :
Colonne < valeur -- ou bien >, <=, >=
Colonne = valeur1 OPERATEUR valeur2 -- ou opérateur est +, -, x, /, % (modulo)
Colonne BETWEEN valeur1 AND valeur2
Colonne LIKE 'valeur%'
Colonne1 = valeur1 AND Colonne2 = valeur2
Colonne IN (valeur1)
EXISTS(...)
Colonne = FONCTION(valeur, ...)
Ne sont pas sargable :
Colonne OPERATEUR valeur2 = valeur1 -- ou opérateur est +, -, x, /, % (modulo) et = peut être remplacé par >, <, >=, <=
Colonne1 = valeur1 OR Colonne2 = valeur2
NOT Colonne = valeur
NOT Colonne < valeur -- ou bien >, <=, >=
NOT Colonne BETWEEN valeur1 AND valeur2
NOT Colonne1 = valeur1 AND Colonne2 = valeur2
Colonne LIKE '%valeur'
Colonne LIKE '%valeur%'
Colonne LIKE 'val%eur'
NOT Colonne LIKE '...'
Colonne NOT LIKE '...'
Colonne IN (valeur1, valeur2)
Colonne NOT IN (...)
NOT Colonne IN (...)
NOT EXISTS(...)
FONCTION(Colonne, ...) = valeur
NOTA : bien que certains prédicats de cette liste soient présentés comme non sargable, certains optimiseurs arrivent à récrire la requête pour rendre le prédicat sargable (algébrisation).
Non sargable, rendu sargable :
Non sargable | récriture sargable
=========================================|======================================
Colonne OPERATEUR valeur2 = valeur1 | Colonne = valeur1 OPERATEUR valeur2
-----------------------------------------|--------------------------------------
Colonne1 = valeur1 OR Colonne2 = valeur2 | Colonne1 = valeur1
| UNION [ALL]
| Colonne2 = valeur2
-----------------------------------------|--------------------------------------
NOT Colonne < valeur | Colonne >= valeur
-----------------------------------------|--------------------------------------
NOT Colonne BETWEEN valeur1 AND valeur2 | Colonne < valeur1
| UNION [ALL]
| Colonne > valeur2
-----------------------------------------|--------------------------------------
Colonne LIKE '%valeur' | ennoloC LIKE 'ruelav%'
-----------------------------------------|-------------------------------------
Colonne LIKE 'val%eur' | Colonne LIKE 'val%'
| INTERSECT
| ennoloC LIKE 'rue%'
-----------------------------------------|-------------------------------------
Colonne IN (valeur1, valeur2) | Colonne = valeur1
| UNION [ALL]
| Colonne = valeur2
NOTA : ennoloC étant le contenu de la colonne « Colonne » inversé (par exemple à l’aide de la fonction REVERSE) et stocké soit en colonne calculée persistante (MS SQL Server), soit sous forme d’index sur expression (PostGreSQL)
À SAVOIR : Il est possible de rendre la recherche de : Colonne LIKE ‘%valeur%’, sargable, en utilisant une technique d’index rotatif que les SGBDR n’ont pas encore intégrés actuellement mais qu’il est possible de simuler dans une table SQL.
3 – TRANSFORMATION SPÉCIFIQUES
Quelques problématiques plus subtiles…
Avec MS SQL Server :
Non sargable | récriture sargable
=========================================|======================================
YEAR(COL_DATE) = 2008 | COL_DATE >= '2008-01-01' AND
| COL_DATE < '2009-01-01'
-----------------------------------------|-----------------------------------------
YEAR(COL_DATE) = 2008 AND | COL_DATE >= '2008-09-01' AND
MONTH(COL_DATE) = 9 | COL_DATE < '2009-01-30'
-----------------------------------------|-----------------------------------------
DATEDIFF(yy, COL_DATE, GETDATE()) > 18 | COL_DATE <= DATEADD(yy, 18, GETDATE())
-----------------------------------------|-----------------------------------------
UPPER(COL_CHAINE) = 'MARTIN' | COL_CHAINE = 'MARTIN'
| COLLATE French_CI_AS
-----------------------------------------|-----------------------------------------
COL_CHAINE = 75001 | COL_CHAINE = '75001'
-----------------------------------------|-----------------------------------------
COL_NOMBRE = '1999' | COL_NOMBRE = 1999
-----------------------------------------|-----------------------------------------
--------
Frédéric Brouard, SQLpro - ARCHITECTE DE DONNÉES, http://sqlpro.developpez.com/
Expert bases de données relationnelles et langage SQL. MVP Microsoft SQL Server
www.sqlspot.com : modélisation, conseil, audit, optimisation, tuning, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
23 Commentaires + Ajouter un commentaire
Commentaires récents
- kahlabourri dans Une seule base de données ou plusieurs ?
- Zabriskir dans Recherches générique dans tous le code procédural de SQL Server
- SQLpro dans Où et comment sont stockées mes données avec PostGreSQL ?
- SQLpro dans Comparatif des fonctionnalités PostGreSQL 9.2 SQL Server 2012
- -kiki- dans MySQL ? Un SGBDR poudre aux yeux !
Archives
- avril 2013
- mars 2013
- février 2013
- octobre 2012
- août 2012
- juillet 2012
- juin 2012
- mai 2012
- avril 2012
- mars 2012
- février 2012
- janvier 2012
- décembre 2011
- novembre 2011
- octobre 2011
- septembre 2011
- août 2011
- juillet 2011
- juin 2011
- mai 2011
- avril 2011
- mars 2011
- février 2011
- janvier 2011
- novembre 2010
- octobre 2010
- septembre 2010
- août 2010
- juillet 2010
- mai 2010
- mars 2010
- février 2010
- janvier 2010
- décembre 2009
- novembre 2009
- octobre 2009
- septembre 2009
- juillet 2009
- juin 2009
- mai 2009
- avril 2009
- mars 2009
- février 2009
- janvier 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- août 2008



Un article de SQLpro
(je viens de remarquer que mon précédent message était incomplet, visiblement les chevrons dans les commentaires ne sont pas échappés s’il ne reconnait pas une balise, bref)
Sont sargable :
Colonne LIKE ‘valeur%’
Ne sont pas sargable :
Colonne LIKE ‘valeur%’
Un oubli dans la correction ou une subtilité que je n’ai pas saisie ?
Au passage, merci pour ce blog instructif
A+
merci pour le signalement de ces erreurs…. La correction n’est pas tout à fait cela, mais c’est corrigé !
A +
Dans la liste SARGABLE, il y a , il est également dans la liste non sargable.
Quand j’ai vu la suite (réécriture sargable), je me suis dit que c’était intentionnel.
Mais je m’interroge sur la réécriture,
Non sargable | récriture sargable
———————–+————————
Colonne LIKE ‘valeur%’ | ennoloC LIKE ‘ruelav%’
A la vue de la réécriture, n’est ce pas ‘%valeur’ au lieu de ‘valeur%’ ? (dans le tableau des transformation spécifique et dans la liste des non sargable).
Autre question, la réécriture de ne serait pas
Colonne LIKE ‘val%’
INTERSECT
ennoloC LIKE ‘rue%’
plutôt que
Colonne LIKE ‘valeur%’
INTERSECT
ennoloC LIKE ‘ruelav%’
?