Cette requête SQL prend 10 secondes:
SELECT * FROM A a JOIN B b on a.idB = b.idB JOIN C c on b.idC = c.idC JOIN D d on c.idD = d.idD JOIN E e ON (e.perimeterId = a.idX AND e.level = X)
Modification de la clause OR avec CASE , la requête prend 3 secondes:
SELECT * FROM A a
JOIN B b on a.idB = b.idB
JOIN C c on b.idC = c.idC
JOIN D d on c.idD = d.idD
JOIN E e ON (
CASE e.level
when 3 then a.idA
when 2 then b.idB
when 1 then c.idC
when 0 then d.idD
END
) = e.perimeterId
Si j'exécute la requête avec une clause OR séparée, les requêtes sont exécutées instantanément Avec notre clause OR :
SELECT * FROM A a
JOIN B b on a.idB = b.idB
JOIN C c on b.idC = c.idC
JOIN D d on c.idD = d.idD
JOIN E e ON((e.perimeterId = a.idA AND e.level = 3)
OR (e.perimeterId = b.idB AND e.level = 2)
OR (e.perimeterId = c.idC AND e.level = 1)
OR (e.perimeterId = d.idD AND e.level = 0))
Comment réécrire ma requête pour être exécutée instantanément ou avec de hautes performances possible?
3 Réponses :
Vous ne voulez que des colonnes de e , donc j'écrirais ceci en utilisant exists:
SELECT e.*
FROM E e
WHERE EXISTS (SELECT 1
FROM a
WHERE e.perimeterId = a.idA AND e.level = 3
) OR
EXISTS (SELECT 1
FROM a JOIN
b
ON a.idB = b.idB
WHERE e.perimeterId = b.idA AND e.level = 2
) OR
EXISTS (SELECT 1
FROM a JOIN
b
ON a.idB = b.idB JOIN
c
ON c.idC = b.idC
WHERE e.perimeterId = c.idA AND e.level = 1
) OR
EXISTS (SELECT 1
FROM a JOIN
b
ON a.idB = b.idB JOIN
c
ON c.idC = b.idC JOIN
d
ON d.idD = c.idD
WHERE e.perimeterId = d.idA AND e.level = 0
);
Je ne suis pas sûr à 100% que les JOIN sont nécessaires dans les sous-requêtes, mais je les ai quand même laissés.
La première requête écrite par OP duplique des lignes. Est intentionnellement ou non est inconnu. Et je suppose que cette performance pourrait être le filtrage des valeurs e.level sur (0,1,2,3)
@AlexYu. . . Je suis tout à fait conscient que les requêtes ne sont pas exactement les mêmes. D'après mon expérience, les doublons ne sont pas souhaitables, mais l'OP peut avoir un cas d'utilisation différent.
@GordonLinoff après avoir réécrit ma requête en suivant votre exemple, cela fonctionne très bien, merci beaucoup, j'accepterai votre message comme réponse
1) créer des index sur a.idB, b.idB, b.idC, c.idC, c.idD, d.idD, e.perimeterId, e.level
2) Essayez ceci
SELECT * FROM A a JOIN B b on a.idB = b.idB JOIN C c on b.idC = c.idC JOIN D d on c.idD = d.idD JOIN E e ON(e.perimeterId = a.idA AND e.level = 3) UNION ALL SELECT * FROM A a JOIN B b on a.idB = b.idB JOIN C c on b.idC = c.idC JOIN D d on c.idD = d.idD JOIN E e ON(e.perimeterId = a.idB AND e.level = 2) UNION ALL SELECT * FROM A a JOIN B b on a.idB = b.idB JOIN C c on b.idC = c.idC JOIN D d on c.idD = d.idD JOIN E e ON(e.perimeterId = a.idC AND e.level = 1) UNION ALL SELECT * FROM A a JOIN B b on a.idB = b.idB JOIN C c on b.idC = c.idC JOIN D d on c.idD = d.idD JOIN E e ON(e.perimeterId = a.idD AND e.level = 0)
La plupart des problèmes de performances sont résolus avec des index bien construits, dans votre clause, essayez toujours d'utiliser les indeces primaires si vous n'avez pas à créer une colonne de filtres correspondante.
Si vous limitez vos données avec
WHERE e.level in (0,1,2,3), que deviendra la première requête?Pouvez-vous clarifier: a) combien de valeurs distinctes de
e.levelavez-vous? b) avez-vous des valeurs en double dans les tableauxA,B,C,DpouridA < / code>,idB,idC?Pourquoi vous joignez-vous à a, b, c, d sans rien sélectionner parmi eux? Vous pouvez simplement faire un
select e. * From e join a on e.preimeterid = a.ida where e.level = 3 union all select e. * From e join b ...c'était une erreur j'ai mis à jour mon message @AlexYu
Ah. Je vois. Mais les questions restent les mêmes. Reformulons-les: a) Avez-vous des doublons dans votre requête de résultat? Si vous ajoutez DISTINCT à vos requêtes, le résultat change-t-il? b) Combien de valeurs distinctes de
e.levelavez-vous? Sont-ils dans la plage[0..4]ou par exemple[0..1024]? c) si vous avez beaucoup dee.levels - que deviendra si vous ajoutezWHERE e.level dans (0,1,2,3)ouO e.level <4et autres?@AlexYu oui il y a des doublons car le résultat après distinct est différent, j'ai 7 niveau, j'ai ajouté la condition
où e.level> = 0car les autres niveaux sont (-3, -2, -1 ) mais la requête reste lente