对于那些对解释感兴趣的人
没有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正在添加限制,当我提出问题时我没有考虑到这一点。
答案 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中有一项改进,推迟了排序后的功能评估。不确定这是否有帮助。