如何提高此 PostgreSQL 查询在索引扫描中的性能
Posted
技术标签:
【中文标题】如何提高此 PostgreSQL 查询在索引扫描中的性能【英文标题】:How to improve this PostgreSQL query's performance in index scan 【发布时间】:2014-12-10 23:28:21 【问题描述】:在这个execution plan 中,以下查询花费了大量时间,3.780 秒,仅对 order_line 表(执行计划的第 11 行)执行索引扫描。
表的主键:
Customer PK - c_w_id, c_d_id, c_id
OOrder PK - o_w_id, o_d_id, o_id
Order_line PK - ol_w_id, ol_d_id, ol_o_id, ol_number
Nation PK - n_nationkey
查询:
select c_id, c_last, sum(ol_amount) as revenue, c_city, c_phone, n_name
from customer, oorder, order_line, nation
where c_id = o_c_id
and c_w_id = o_w_id
and c_d_id = o_d_id
and ol_w_id = o_w_id
and ol_d_id = o_d_id
and ol_o_id = o_id
and o_entry_d >= '2007-01-02 00:00:00.000000'
and o_entry_d <= ol_delivery_d
and n_nationkey = ascii(substr(c_state,1,1))
group by c_id, c_last, c_city, c_phone, n_name
order by revenue desc
如何提高此查询的性能?你推荐什么物化视图?这是一个好的选择吗?
CREATE MATERIALIZED VIEW mview AS
select c_id, c_last, ol_amount, c_city, c_phone, o_entry_d, ol_delivery_d, c_state
from customer, oorder, order_line
where c_id = o_c_id
and c_w_id = o_w_id
and c_d_id = o_d_id
and ol_w_id = o_w_id
and ol_d_id = o_d_id
and ol_o_id = o_id;
【问题讨论】:
你能做一个explain select ...
并发布输出吗?
您可以在发布的执行计划中看到这一点……在哪里说 TEXT。谢谢
很酷的 postgresql 查询解释网站 :)
我也有同样的看法,真的很好:)
【参考方案1】:
-
切勿使用此类列名。
如果不是 1) 则永远不要在查询中写入没有表前缀的列名(无需在列名中添加前缀)。
最好在“join”子句中编写连接,而不是在“where”子句中,这样您就可以使用连接的层次结构进行操作。
最后,你跑了吗
analyse customer;
analyse order_line;
analyse oorder;
analyse nation;
在 ascii(substr(c_state,1,1)) 上添加索引后? 如果没有 - 运行它。
您还可以在 select 子句中将 n_name 作为子查询:
select c_id, c_last, revenue, c_city, c_phone, (select x.n_name from nation x where x.n_nationkey = ascii(c_statecut)) as n_name
from (
select c_id, c_last, sum(ol_amount) as revenue, c_city, c_phone, substr(c_state,1,1) as c_statecut
from customer, oorder, order_line
where c_id = o_c_id
and c_w_id = o_w_id
and c_d_id = o_d_id
and ol_w_id = o_w_id
and ol_d_id = o_d_id
and ol_o_id = o_id
and o_entry_d >= '2007-01-02 00:00:00.000000'
and o_entry_d <= ol_delivery_d
group by c_id, c_last, c_city, c_phone, c_statecut
) finale
order by revenue desc
国家表是一个简单的查找表,但它会影响聚合的整体计划。
关于物化视图,单独使用 order_line 表的预聚合是获取总数的最快方法,但就查询中的“o_entry_d
select o_c_id, ol_w_id, ol_d_id, ol_o_id, sum(ol_amount)
from order_line
join oorder
on ol_w_id = o_w_id
and ol_d_id = o_d_id
and ol_o_id = o_id
and o_entry_d <= ol_delivery_d -- (very strange condition, which looks redundant... it could be better if you can remove it)
where o_entry_d >= '2007-01-02 00:00:00.000000'
group by o_c_id, ol_w_id, ol_d_id, ol_o_id
如果此查询大约需要 3 秒,则将其具体化。如果少于 3 秒,那么您可以即时加入它。
【讨论】:
我明白你的建议,但没有帮助。此外,现在花更多的时间。【参考方案2】:您可以尝试使用ascii(substr(c_state,1,1))
的表达式索引。您对客户进行顺序扫描。
【讨论】:
以上是关于如何提高此 PostgreSQL 查询在索引扫描中的性能的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使使用仅索引扫描 PostgresQL 计数也如此缓慢