Bonjour à tous.
Désolé de vous déranger avec un problème aussi simple mais je suis en train de me demander si je ne suis pas fou.
Soit 4 tables :
T0 : 100 lignes, 3 champs dont 1 clé primaire Id
T1 : 20 000 lignes, 5 champs dont le champ Id, pas de clé primaire, pas d'index
T2 : 30 000 lignes, 5 champs dont le champ Id, pas de clé primaire, pas d'index
T3 : 100 lignes, 5 champs dont le champ Id, pas de clé primaire, pas d'index
Le besoin fonctionnel est le suivant : filtrer T0 en ne prenant que les lignes dont Id existe dans les 3 autres tables.
En SQL pur on ferait :
SELECT Id from T0 WHERE EXISTS (SELECT 1 FROM T1 WHERE T1.Id = T0.Id) AND EXISTS (SELECT 1 FROM T2 WHERE T2.Id = T0.Id) And EXISTS (SELECT 1 FROM T3 WHERE T3.Id = T0.Id)
Mais je ne peux pas utiliser EXISTS (requête générée automatiquement) donc la solution adoptée était :
SELECT distinct Id from T0 WHERE T1.Id = T0.Id AND T2.Id = T0.Id AND T3.Id = T0.Id)
Cette solution a bien marché pendant un moment et brusquement la requête s'est mis à durer des heures.
Le plan d'exécution est affreux (des MERGE JOIN (CARTESIAN) entre T1, T2 et T3 puis des NESTED LOOP avec T0).
J'ai d'abord pensé que le problème venait que les statistiques n'étaient pas calculées (ce qui était le cas) donc on les a calculées mais le plan d'exécution n'a pas bougé.
La solution d'indexer les champs des tables T1, T2 et T3 n'est pas possible pour des raisons d'architecture (tables de travail droppées et re-créées à la volée, etc.).
2 solutions ont été trouvées :
La première, la plus propre pour moi :
SELECT distinct Id from T0, T1, T2, T3 WHERE T1.Id = T0.Id AND T2.Id = T1.Id AND T3.Id = T2.Id
La 2e, qui me fait halluciner parce qu'effectivement les temps redeviennent normaux (je n'ai pas le plan d'exécution, peut-être demain)
SELECT distinct Id from T0, T1, T2, T3 WHERE T1.Id = T0.Id AND T2.Id = T0.Id AND T3.Id = T0.Id AND T2.Id = T1.Id AND T3.Id = T2.Id AND T1.Id = T3.Id
M'enfin moi ça me fait halluciner ce genre de comportement... Mais c'est peut-être courant avec des tables non indexées...
EDIT : je suis un abruti qui ne se relit pas je suis un abruti qui ne se relit pas je suis un abruti qui ne se relit pas je suis un abruti qui ne se relit pas je suis un abruti qui ne se relit pas je suis un abruti qui ne se relit pas je suis un abruti qui ne se relit pas ...
Partager