SQL-IN(选择...)性能问题

时间:2019-06-14 19:37:23

标签: sql performance select

我知道应该避免使用(选择...)东西,但是在我的情况下,我找不到其他方法来做到这一点。

不幸的是,由于数据库很大,所以我想找到一种更好的方法。所以,请您分享您的经验以优化下面的查询?

这是数据库的想法

ID   OrderRef   Product    OrderDate   ShipmentDate    Client

1    111        T-Shirt    1/1/2018    4/1/2018        Georges
2    111        Pull-Over  1/1/2018    6/1/2018        (Unknown)
3    222        Shoes      9/1/2018    15/1/2018       Austin
4    222        T-Shirt    9/1/2018    18/1/2018       (Unknown)

我需要检索的是:

  • 与Georges订单相关的数据(此处为第1和2行)。但是如您所见,第二行中的“客户端”是“未知”。
  • 链接到按“参考”分组的特定订单的最新发货日期(-> max(t2.ShipmentDate))

这是我的代码

SELECT t1.OrderRef, t1.Product, t1.OrderDate, t1.Client, t4.max_date
FROM table1 as t1
RIGHT JOIN (SELECT t2.OrderRef, max(t2.ShipmentDate) as max_date
            FROM table1 as t2
            WHERE t2.OrderRef in(
                            SELECT t3.OrderRef 
                            FROM table1 as t3
                            WHERE t3.Client='Georges')
            GROUP BY t2.OrderRef) as t4 on t2.OrderRef=t1.OrderRef

正确的联接在那里仅检索链接到Georges的OrderReference,以及子查询以计算最新的ShipmentDate

  • 有没有更有效的方法来达到这个结果?
  • 因为t1,t2,t3链接到同一张表。我认为这种方式更具可读性,但是出于性能方面的考虑,我应该仅对它们使用一个名称吗?

在此先感谢您的帮助, 拉哥

2 个答案:

答案 0 :(得分:2)

您似乎只在每次调用时检索几行。即使您有数十亿行,这也应该非常快。我会做类似的事情:

with
a as (
  select max(orderref) as orderref
  from t
  where client = 'Georges'
),
b as (
  select t.* 
  from t
  join a on a.orderref = t.orderref
),
c as (
  select max(shipmentdate) as maxshipmentdate from b
)
select b.*, c.maxshipmentdate
from b
cross join c 

上面的查询应该很快,因为您具有以下索引:

create index ix1 on t (client);
create index ix2 on t (orderref);

答案 1 :(得分:0)

我会尝试使用(相关的)子查询。

SELECT t11.orderref,
       t11.product,
       t11.orderdate,
       t11.client,
       (SELECT max(t13.shipmentdate)
               FROM table1 t13
               WHERE t13.orderref = t11.orderref) max_date
       FROM table1 t11
       WHERE t11.orderref = (SELECT t12.orderref
                                    FROM table1 t12
                                    WHERE t12.client = 'Georges');

为了支持子查询获得orderref这样的索引

CREATE INDEX table1_c_or
             ON table1 (client ASC,
                        orderref ASC);

应该有帮助。该子查询仍然是“尖的”。

获取最大的shipmentdate

CREATE INDEX table1_or_sd
             ON table1 (orderref ASC,
                        shipmentdate DESC);

应该有帮助。优化器应注意,由于orderref始终相同,因此只需要检索一次最大值。该索引也可以用来支持外部查询,因为orderref是它的第一个关键字。

(可选)创建其他索引,例如

CREATE INDEX table1_or_p_od_c
             ON table1 (orderref ASC,
                        product ASC,
                        orderdate ASC,
                        client ASC);

甚至可以更好地支持外部查询。但这不是必需的。