如何提高此PostgreSQL查询在索引扫描中的性能

如何提高此PostgreSQL查询在索引扫描中的性能,sql,postgresql,database-indexes,Sql,Postgresql,Database Indexes,在这种情况下,下面的查询花费了大量时间(3.780秒)仅对执行计划的order_line表第11行执行索引扫描 表的主键: 客户主键-c_w_id、c_d_id、c_id 订单主键-o_w_id,o_d_id,o_id 订单行主键-ol_w_id、ol_d_id、ol_o_id、ol_编号 国家PK-n_国家密钥 查询: 选择c_id、c_last、sumol_amount作为收入、c_city、c_phone、n_name 来自客户、订单、订单行、国家 其中c_id=o_c_id c_w_id

在这种情况下,下面的查询花费了大量时间(3.780秒)仅对执行计划的order_line表第11行执行索引扫描

表的主键:

客户主键-c_w_id、c_d_id、c_id 订单主键-o_w_id,o_d_id,o_id 订单行主键-ol_w_id、ol_d_id、ol_o_id、ol_编号 国家PK-n_国家密钥 查询:

选择c_id、c_last、sumol_amount作为收入、c_city、c_phone、n_name 来自客户、订单、订单行、国家 其中c_id=o_c_id c_w_id=o_w_id c_d_id=o_d_id 和ol_w_id=o_w_id 而ol_d_id=o_d_id 并且ol_o_id=o_id 和o_entry_d>='2007-01-02 00:00:00.000000'
而o_entry_d您可以尝试使用asciisubstrc_状态的表达式索引,1,1。您对客户进行了顺序扫描

永远不要使用这样的列名。 如果不是1,则永远不要在查询中写入没有表前缀的列名,无需在列名中添加前缀。 最好在join子句中编写联接,而不是在where子句中编写联接,这样就可以使用联接的层次结构进行操作。 最后,你跑了吗

analyse customer; 
analyse order_line; 
analyse oorder; 
analyse nation;
在asciisubstrc_状态上添加索引后,1,1? 如果没有-运行它

您还可以在select子句中将n_名称作为子查询获取:

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
Nation表是一个易于查找的表,但它会影响聚合的总体计划


关于物质化视图,单是订单行表的预聚合是获取总计的最快方法,但只要您有o_条目,您就可以进行解释选择。。。并发布输出。您可以在发布的执行计划中看到这一点。。。在哪里说文字。Thankscool postgresql查询解释网站:我有相同的意见,真的很好:我知道你的建议,但没有帮助。此外,现在花更多的时间。
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
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