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.level
avez-vous? b) avez-vous des valeurs en double dans les tableauxA
,B
,C
,D
pouridA < / 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.level
avez-vous? Sont-ils dans la plage[0..4]
ou par exemple[0..1024]
? c) si vous avez beaucoup dee.level
s - que deviendra si vous ajoutezWHERE e.level dans (0,1,2,3)
ouO e.level <4
et 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> = 0
car les autres niveaux sont (-3, -2, -1 ) mais la requête reste lente