我的数据库(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在我放"加入"时会忽略索引外面看?
谢谢。