与OR子句的SQL查询性能

问题描述 投票:2回答:1

这个SQL查询需要10秒:

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))

更改或与CASE子句,查询需要3秒:

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 

如果我执行有独立的OR子句的查询时,查询立即执行全无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.idX AND e.level = X) 

如何重写我的查询将立即执行或高性能可能吗?

sql sql-server-2017
1个回答
2
投票

您只希望从e列,所以我会用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
             );

我不知道该JOINs需要在子查询100%,但我已经离开他们,无论如何。


0
投票

1)上a.idB,b.idB,b.idC,c.idC,c.idD,d.idD,e.perimeterId,E.LEVEL创建索引

2)试试这个

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) 
© www.soinside.com 2019 - 2024. All rights reserved.