缓慢计划访问视图

时间:2016-07-15 11:52:10

标签: postgresql

我们有一个有点复杂的表连接并创建了一个视图,以避免为每次使用编写它。简化......

create view MyView as
select b.id,b.customer_id,b.somedata,t1.moredata
from bigtable b
left join table1 t1 on t1.id=b.t1_id

当它本身使用时,它按预期工作,并在几毫秒内返回行。

select *
from MyView
where customer_id=somevalue    -- That's ok

但现实生活并非如此简单。实际上,我们希望将它用作更复杂查询的一部分:

select *
from Customers c
left join MyView v on v.customer_id=c.id
where c.code=somecustomercode      -- Simple enough ... but problematic

我们期待快速回答,使用现有索引读取客户表,并在客户已经解决的情况下离开加入视图。

但它需要永远(bigtable有几十万行)。

使用explain告诉我们原因:首先创建整个视图,然后执行customer表连接作为最后一步。

关于如何改进(使其有效)的任何想法?

已编辑以添加(简化)实际视图以及解释文字。我们正在使用PostgreSQL 9.1.20。实际视图还有两个表更复杂,但这个表有相同的行为。

视图

CREATE OR REPLACE VIEW MyView AS 
 SELECT trim(ip.res_id, 'res.partner,')::integer AS partner_id,
  ppli.product_id,
  ppli.fixed_price
   FROM ir_property ip
   LEFT JOIN product_pricelist ppl ON ppl.id = trim(ip.value_reference, 'product.pricelist,')::integer AND ppl.type = 'c'
      LEFT JOIN product_pricelist_item ppli ON ppli.pricelist_id = ppl.id AND ppli.product_id is not null
    AND now() between COALESCE(ppli.date_start, '2016-01-01'::date) AND COALESCE(ppli.date_end, '2099-12-31'::date)
  WHERE ip.name = 'property_product_pricelist' AND left(ip.res_id, length('res.partner,')) = 'res.partner,' 
    AND left(ip.value_reference, length('product.pricelist,')) = 'product.pricelist,';

解释使用customer_id直接访问视图的第一个(快速)选择

select *
from MyView
where partner_id=12345

''Nested Loop Left Join  (cost=0.01..3920.07 rows=8 width=32)'
'  ->  Nested Loop Left Join  (cost=0.01..3897.79 rows=1 width=24)'
'        ->  Seq Scan on ir_property ip  (cost=0.00..3889.49 rows=1 width=42)'
'              Filter: (((name)::text = 'property_product_pricelist'::text) AND ("left"((res_id)::text, 12) = 'res.partner,'::text) AND ("left"((value_reference)::text, 18) = 'product.pricelist,'::text) AND ((btrim((res_id)::text, 'res.partner,'::text))::integer = 128930))'
'        ->  Index Scan using product_pricelist_pkey on product_pricelist ppl  (cost=0.01..8.28 rows=1 width=4)'
'              Index Cond: (id = (btrim((ip.value_reference)::text, 'product.pricelist,'::text))::integer)'
'              Filter: ((type)::text = 'c'::text)'
'  ->  Index Scan using product_pricelist_item_pricelist__product_index on product_pricelist_item ppli  (cost=0.00..22.06 rows=13 width=16)'
'        Index Cond: ((pricelist_id = ppl.id) AND (product_id IS NOT NULL))'
'        Filter: ((now() >= COALESCE(date_start, '2016-01-01'::date)) AND (now() <= COALESCE(date_end, '2099-12-31'::date)))'

解释第二个(慢)选择访问视图作为连接

select customer_id,v.*
from res_partner c
left join MyView v on v.partner_id=c.id
where c.ref='Code01'

'Nested Loop Left Join  (cost=0.01..3293.42 rows=1 width=1300)'
'  Join Filter: ((btrim((ip.res_id)::text, 'res.partner,'::text))::integer = rp.id)'
'  ->  Index Scan using res_partner_ref_index on res_partner rp  (cost=0.00..8.32 rows=1 width=1268)'
'        Index Cond: ((ref)::text = 'Code01'::text)'
'  ->  Nested Loop Left Join  (cost=0.01..3284.93 rows=8 width=32)'
'        ->  Nested Loop Left Join  (cost=0.01..3209.33 rows=1 width=24)'
'              ->  Seq Scan on ir_property ip  (cost=0.00..3201.03 rows=1 width=42)'
'                    Filter: (((name)::text = 'property_product_pricelist'::text) AND ("left"((res_id)::text, 12) = 'res.partner,'::text) AND ("left"((value_reference)::text, 18) = 'product.pricelist,'::text))'
'              ->  Index Scan using product_pricelist_pkey on product_pricelist ppl  (cost=0.01..8.28 rows=1 width=4)'
'                    Index Cond: (id = (btrim((ip.value_reference)::text, 'product.pricelist,'::text))::integer)'
'                    Filter: ((type)::text = 'c'::text)'
'        ->  Index Scan using product_pricelist_item_pricelist__product_index on product_pricelist_item ppli  (cost=0.00..75.43 rows=13 width=16)'
'              Index Cond: ((pricelist_id = ppl.id) AND (product_id IS NOT NULL))'
'              Filter: ((now() >= COALESCE(date_start, '2016-01-01'::date)) AND (now() <= COALESCE(date_end, '2099-12-31'::date)))'

0 个答案:

没有答案