问题
I have a table in my DB (Postgres 9.3.4) with index on couple of columns. Also I have a view based only on this table with grouping and filter by indexed columns.
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;
When I select some data from this view - I get an index scan in execution plan - all as wanted.
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"
But when I join this view with any other table I get an sequence scan... so index is ignored for some reason.
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"
If I set enable_seqscan to 'off' - then instead of sequence scan I get an Bitmap index scan/Bitmap heap scan.
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"
But, when I put join inside view (new view vstatement_base1 created) - then I get correct index scan as i first case.
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"
So... can anybody tell me - why postgres ignores index when I put "join" outside view?
Thank You.
来源:https://stackoverflow.com/questions/27142333/index-is-ignored-on-joined-view-in-postgres