当包含WHERE语句时,为什么此查询会花费更长的时间?

时间:2018-01-31 23:58:52

标签: sql postgresql postgresql-9.4

对于那些对解释感兴趣的人

没有WHERE:https://explain.depesz.com/s/XaDH

使用WHERE:https://explain.depesz.com/s/iPOL

我有一个视图,我可以在519毫秒内选择*并接收500多行,如果我添加WHERE ordernumber = 165973(或任何订单号)需要18秒。查询规划器也确信这两个查询都需要大约18秒,但是没有where条件,它每次都会在~500ms内完成。

CREATE VIEW v_recent_api_panels AS
  SELECT DISTINCT ON (s.barcode) s.barcode,
    s.ordernumber,
    production.machine_data_box(d.datastring) AS box,
    c."Edate",
    c."SDate",
    p.height,
    p.width,
    p.blankheight,
    p.blankwidth,
    p.paneltype,
    p.dateprocessed,
    p.listnum,
    p.material,
    p.color,
    p.boxnumber,
    p.location,
    p.cutout_param,
    s.lastmodified,
    p.machinetype,
    'NULL'::text AS status,
    (((((date_part('year'::text, p.danobatfab) || '-'::text) || date_part('month'::text, p.danobatfab)) || '-'::text) || date_part('day'::text, p.danobatfab)))::date AS danobatfab,
    p.fabdate AS originalfabdate
   FROM (((production.mv_recent_schedules s
     LEFT JOIN workorders.mv_recent_panel_details p ON ((p.barcode = s.barcode)))
     LEFT JOIN cupra.mv_parts c ON (((c."PrdRef")::text = s.barcode)))
     LEFT JOIN production.mv_machine_data d ON ((d.barcode = p.barcode)))
  WHERE (p.ordernumber IS NOT NULL)
  ORDER BY s.barcode;

编辑:我的postgres客户端(datagrip)在查询中添加了一个隐式LIMIT 500,只有在没有WHERE语句的情况下才能有效使用。 更改了此问题的标题以反映我的发现。

编辑2:我不知道是否应该保留这个问题或删除它,因为它相当愚蠢,但答案是select *语句LIMIT 500只需要评估它的前500行发生了,但WHERE强迫它评估所有这些。我的sql cient正在添加限制,当我提出问题时我没有考虑到这一点。

1 个答案:

答案 0 :(得分:1)

必定存在错误:快速执行计划显示执行时间为18秒。它还返回68489行而不是500。

问题在于你的职能production.machine_data_box;它负责几乎所有的执行时间。

问题是始终为所有271651行评估函数,因为WHERE条件只能在视图查询完成后应用,因为您使用DISTINCT

我有几个改进的想法:

  • 删除ORDER BY。它应该在使用视图的查询中。

  • 不要将DISTINCT ON放入视图中。然后,在评估了您的额外条件后,您可以将其放入查询中,如果可能的话。

  • 使用COST = 1000或更高版本将该功能标记为昂贵。然后优化器会更喜欢不经常调用该函数的计划。除非你摆脱DISTINCT ON,否则这可能不会有帮助,但这肯定是正确的。

  • 如果可以,请重写该功能,使其更快。

  • 升级到PostgreSQL 9.6或更高版本。 9.6中有一项改进,推迟了排序后的功能评估。不确定这是否有帮助。