繁体   English   中英

由于糟糕的执行计划,查询时间急剧增加

[英]Query time increases dramatically due to poor execution plan

我有一个相对复杂的查询,如下面的查询

select * from (
  select
      distinct on("car")
      entity.id as "car",
      metric as "last_visit"
  from now() ref_date
  cross join (values (142), (432), (583), (448), (381)) entity(id)
  left join (
    select
        gv.car_id as _entity_id,
        gv.start as _tc_past,
        gv.start as _keep_max_of,
        g.name as metric
    from garage_visits gv
    left join garage_tree_flat gtf on gtf.descendant_id = gv.garage_id
    left join garage g on g.id = gtf.parent_id
    where true
    and price != 0
    and  g.type = 2
  ) x
  on x._entity_id = entity.id
    and _tc_past < ref_date
    and _tc_past >= ref_date - interval '12 weeks'
    order by "car", _keep_max_of desc
) t
where t."last_visit" is not null;

我的问题是查询运行时间会根据cross join (values (...))而有很大差异。

也就是说,我有以下平均运行时间,具体取决于有多少values

价值观 平均运行时间
1 25毫秒
2 30ms
3 35毫秒
4 40毫秒
5 4900毫秒
6 4900毫秒
7 4900毫秒

检查两个版本的执行计划(最多 3 个值或超过 3 个值)表明罪魁祸首是garage_visits gv上的索引扫描。 该表包含数百万行。

在最多 3 个car_ids garage_visits的索引条件如下:

Node Type: Index Scan
Index Name: ix_gv_car_id
Index Cond: (gv.car_id = "*VALUES*".column1)
Actual Duration: 0.687ms

garage_visits超过 3 个的情况下, car_ids上的索引条件如下:

Node Type: Index Scan
Index Name: ix_gv_garage_id
Index Cond: (gv.garage_id = gtf.descendant_id)
Actual Duration: 3386.068ms

正如我们所观察到的,查询规划器决定通过car_id过滤garage_visits最多三个值,并仅输出这些行,这非常快。 但是对于超过三个 car_id 值,规划器决定不使用此信息,而是通过gtf.descendant_id过滤garage_visits ,这极大地改变了执行时间,因为gtf.descendant_id值比car_ids值多得多。

有没有办法继续使用“最多 3 个值”的方式但超过 3 个值? 看起来这只是查询规划器的一个错误估计,令人沮丧的是,这个查询可以运行得非常快(即使是 30 或 50 个值),但却浪费了大量时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM