Je vous sollicite au sujet d'une requête qui me donne quelques soucis.
Le premier point à considérer, c'est que je ne peux pas en changer la structure des tables, ni influer sur les règles de gestion précisées ci-dessous. Je peux juste jouer sur la requête et les index.
La requête a pour but de déterminer le prix d'un article, sachant que le prix peut être :
> unique par site ou bien le même pour tous les sites
> unique par dimension (couleur, taille, etc.) ou bien le même pour toutes les dimensions de l'article
De plus on recherche le dernier prix pour cet article en terme de date de création, sachant qu'il peut bien évidemment avoir un historique de plusieurs prix.
En fait, c'est cette triple hypothèse qui va me poser des problèmes de perf lors de l'exécution de la requête de recherche de prix, même si le nombre d'articles et de prix n'est vraiment pas démentiel (23 000 articles et 33 000 prix).
Voici les champs de la table utilisés dans la requête :
1 2 3 4 5 6 7
| CREATE TABLE ARTICLEPRIX
(
SITE CHAR(1) --> site auquel le prix est à appliquer
ARTICLE CHAR(2) --> code de l'article
DATE SMALDATETIME --> date de début du prix
PRIX INTEGER --> prix de l'article pour un site et une date donnés
) |
Si le champ SITE='A', cela veut dire que le prix est spécifique au site A.
Si le champ SITE='', cela veut dire que le prix est commun à l'ensemble des sites.
Article non dimensionné : ARTICLE='1 ' où '1' est le code de l'article et ' ' signifie qu'il n'a pas de dimension
Article dimensionné : ARTICLE='2G' où '2' est le code de l'article et 'G' correspond à la dimension G.
Si pour l'article n°3 dimensionné, le prix est commun à l'ensemble des dimensions, alors une seule ligne de prix est crée avec ARTICLE='3 ' (donc comme pour un article non dimensionné)
Si pour un article n°4 dimensionné, le prix est spécifique pour une ou plusieurs dimensions, alors une ligne de prix est crée par dimension avec un prix spécifique (ARTICLE='4A', ARTICLE='4B', ARTICLE='4C', etc.) et une ligne est crée pour toutes les autres dimensionnés qui ont un prix commun (ARTICLE='4 ').
Ces règles un peu mieux précisées, voici la requête :
SELECT TOP 1 PRIX FROM ARTICLEPRIX WHERE (SITE=[le site à chercher] OR SITE='') AND (ARTICLE=[code de l''article] OR ARTICLE=LEFT([code de l''article],1) + ' ') AND DATE <= [date à chercher] ORDER BY DATE DESC, ARTICLE DESC, SITE DESC
La requête en elle-même semble toute bête mais les deux clauses (SITE=[le site à chercher] OR SITE='') et (ARTICLE=[code de l'article] OR ARTICLE=LEFT([code de l''article],1) + ' ') augmentent les temps de traitement de façon exponentielle. Par contre si l'on utilise uniquement l'une ou l'autre, les temps de traitement chutent énormément.
La base tourne sur un SQL Server 2000.
En terme d'index, j'ai créé celui-ci qui est parfaitement inefficace :
1 2
| CREATE INDEX X_PRIX_INDEX1
ON ARTICLEPRIX (ARTICLE ASC, SITE ASC, DATE DESC) |
Pour donner un ordre d'idée, pour 100 articles, la requête prend 1.5s, mais pour 1000 articles elle prend 38s. Je vous laisse deviner pour 10000 articles ....
Auriez-vous une idée sur la façon d'optimiser la requête ou d'indexer plus efficacement la table ? Merci d'avance.
Partager