Postgres中的联接视图将忽略索引

时间:2014-11-26 06:00:50

标签: postgresql view indexing

我的数据库(Postgres 9.3.4)中有一个表,其中有几列的索引。另外,我的视图仅基于此表,并按索引列进行分组和过滤。

    CREATE OR REPLACE VIEW vstatement_base AS                               
     SELECT o.bitrnrequestid AS bitrnreqid,                                 
        o.icardid,                                                          
        o.icardaccountid,                                                   
        o.iterminalid,                                                      
        abs(sum(                                                            
            CASE                                                            
                WHEN o.sitypeex = ANY (ARRAY[1, 11]) THEN o.namount         
                ELSE 0::numeric                                             
            END)) AS charged,                                               
        abs(sum(                                                            
            CASE                                                            
                WHEN o.sitypeex = ANY (ARRAY[2, 12]) THEN o.namount         
                ELSE 0::numeric                                             
            END)) AS withdrawn                                              
       FROM ttrnoperations o                                                
      WHERE o.sicommitstate >= 1 AND o.bcancelled = false                   
      GROUP BY o.bitrnrequestid, o.icardid, o.icardaccountid, o.iterminalid;

当我从这个视图中选择一些数据时 - 我在执行计划中得到一个索引扫描 - 全部按需要。

   query: 
   select * from ls.vstatement_base limit 100  

   execution plan:
   "Limit  (cost=0.42..200.73 rows=100 width=276) (actual time=0.088..1.614 rows=100 loops=1)"
   "  ->  GroupAggregate  (cost=0.42..806065.36 rows=404438 width=33) (actual time=0.086..1.601 rows=100 loops=1)"
   "        ->  Index Scan using ix_ttrnoperations_vstmt_base_id on ttrnoperations o  (cost=0.42..751384.32 rows=850958 width=33) (actual time=0.027..0.393 rows=239 loops=1)"
   "              Filter: ((NOT bcancelled) AND (sicommitstate >= 1))"
   "Total runtime: 1.749 ms"

但是当我将这个视图与任何其他表连接起来时,我得到一个序列扫描...所以索引因某种原因被忽略。

    query:
    select * from ls.vstatement_base v, ttrnrequests tr WHERE v.bitrnreqid=tr.biid  limit 100  

   execution plan:
   "Limit  (cost=157369.84..157396.40 rows=100 width=368) (actual time=992.271..992.802 rows=100 loops=1)"
   "  ->  Merge Join  (cost=157369.84..264813.66 rows=404438 width=368) (actual time=992.269..992.790 rows=100 loops=1)"
   "        Merge Cond: (o.bitrnrequestid = tr.biid)"
   "        ->  GroupAggregate  (cost=157369.42..214177.85 rows=404438 width=33) (actual time=992.246..992.692 rows=100 loops=1)"
   "              ->  Sort  (cost=157369.42..159496.81 rows=850958 width=33) (actual time=992.211..992.251 rows=239 loops=1)"
   "                    Sort Key: o.bitrnrequestid, o.icardid, o.icardaccountid, o.iterminalid"
   "                    Sort Method: external merge  Disk: 36520kB"
   "                    ->  Seq Scan on ttrnoperations o  (cost=0.00..27012.46 rows=850958 width=33) (actual time=0.074..292.888 rows=851049 loops=1)"
   "                          Filter: ((NOT bcancelled) AND (sicommitstate >= 1))"
   "                          Rows Removed by Filter: 988"
   "        ->  Index Scan using pk_ttrnrequests_biid on ttrnrequests tr  (cost=0.42..40509.61 rows=410539 width=92) (actual time=0.018..0.044 rows=100 loops=1)"
   "Total runtime: 996.706 ms"

如果我将enable_seqscan设置为' off' - 然后我得到一个Bitmap索引扫描/位图堆扫描而不是序列扫描。

    execution plan:
    "Limit  (cost=175445.88..175472.45 rows=100 width=368) (actual time=114.157..1141.831 rows=100 loops=1)"
    "  ->  Merge Join  (cost=175445.88..282889.70 rows=404438 width=368) (actual time=1141.155..1141.823 rows=100 loops=1)"
    "        Merge Cond: (o.bitrnrequestid = tr.biid)"
    "        ->  GroupAggregate  (cost=175445.46..232253.90 rows=404438 width=33) (actual time=1141.113..1141.640 rows=100 loops=1)"
    "              ->  Sort  (cost=175445.46..177572.86 rows=850958 width=33) (actual time=1141.078..1141.122 rows=239 loops=1)"
    "                    Sort Key: o.bitrnrequestid, o.icardid, o.icardaccountid, o.iterminalid"
    "                    Sort Method: external merge  Disk: 36520kB"
    "                    ->  Bitmap Heap Scan on ttrnoperations o  (cost=18089.53..45088.51 rows=850958 width=33) (actual time=88.872..445.549 rows=851049 loops=1)"
    "                          Recheck Cond: (sicommitstate >= 1)"
    "                          Filter: (NOT bcancelled)"
    "                          Rows Removed by Filter: 363"
    "                          ->  Bitmap Index Scan on ix_ttrnoperations_vstmt_base_state  (cost=0.00..17876.80 rows=850958 width=0) (actual time=87.335..87.335 rows=851049 loops=1)"
    "                                Index Cond: ((sicommitstate >= 1) AND (bcancelled = false))"
    "        ->  Index Scan using pk_ttrnrequests_biid on ttrnrequests tr  (cost=0.42..40509.61 rows=410539 width=92) (actual time=0.039..0.120 rows=100 loops=1)"
    "Total runtime: 1145.811 ms"

但是,当我将join放入视图内部时(创建了新视图vstatement_base1) - 然后我得到正确的索引扫描,就像我的第一种情况一样。

    query:
    select * from ls.vstatement_base1 v limit 100  

   execution plan:
    "Limit  (cost=175.92..695.41 rows=100 width=276) (actual time=0.108..2.412 rows=100 loops=1)"
    "  ->  GroupAggregate  (cost=175.92..2097148.02 rows=404438 width=33) (actual time=0.106..2.389 rows=100 loops=1)"
    "        ->  Merge Join  (cost=175.92..2042466.98 rows=850958 width=33) (actual time=0.051..0.999 rows=239 loops=1)"
    "              Merge Cond: (o.bitrnrequestid = tr.biid)"
    "              ->  Index Scan using ix_ttrnoperations_vstmt_base_id on ttrnoperations o  (cost=0.42..1444271.58 rows=850958 width=33) (actual time=0.018..0.560 rows=239 loops=1)"
    "                    Filter: ((NOT bcancelled) AND (sicommitstate >= 1))"
    "              ->  Materialize  (cost=0.42..584386.07 rows=410539 width=8) (actual time=0.025..0.205 rows=239 loops=1)"
    "                    ->  Index Only Scan using pk_ttrnrequests_biid on ttrnrequests tr  (cost=0.42..583359.73 rows=410539 width=8) (actual time=0.018..0.120 rows=101 loops=1)"
    "                          Heap Fetches: 101"
    "Total runtime: 2.615 ms"

所以...任何人都可以告诉我 - 为什么postgres在我放"加入"时会忽略索引外面看?

谢谢。

0 个答案:

没有答案