Re: [HACKERS] No Index-Only Scan on Partial Index

2013-10-03 Thread David E. Wheeler
On Oct 2, 2013, at 5:07 AM, Merlin Moncure mmonc...@gmail.com wrote:

  Hrm. I get a seq scan for that query:
 
  create index on try(upper_inf(irange));
  explain select * from try where upper_inf(irange);
  QUERY PLAN
  ---
   Seq Scan on try  (cost=0.00..1887.00 rows=3 width=68)
 Filter: upper_inf(irange)
 
  True also if I just select the irange. Is the filter the issue, here?
 
 Turn off seq scan...

That rewards me with a bitmap heap scan:

EXPLAIN select * from try where upper_inf(irange);

  QUERY PLAN
  
--
 Bitmap Heap Scan on try  (cost=935.63..2197.63 rows=3 width=68)
   Filter: upper_inf(irange)
   -  Bitmap Index Scan on try_upper_inf_idx  (cost=0.00..927.30 rows=5 
width=0)
 Index Cond: (upper_inf(irange) = true)

But anyway, I still don’t understand why, if the function used to store the 
value is immutable (as upper_inf() is), why Postgres doesn't do an index scan. 
Is this something that could be improved in the planner?

Thanks,

David



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] No Index-Only Scan on Partial Index

2013-10-03 Thread Josh Berkus
David,

 But anyway, I still don’t understand why, if the function used to store the 
 value is immutable (as upper_inf() is), why Postgres doesn't do an index 
 scan. Is this something that could be improved in the planner?

Yes.  This is clearly a TODO.

-- 
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] No Index-Only Scan on Partial Index

2013-10-03 Thread David E. Wheeler
On Oct 3, 2013, at 10:50 AM, Josh Berkus j...@agliodbs.com wrote:

 
 But anyway, I still don’t understand why, if the function used to store the 
 value is immutable (as upper_inf() is), why Postgres doesn't do an index 
 scan. Is this something that could be improved in the planner?
 
 Yes.  This is clearly a TODO.

Added it here:

  https://wiki.postgresql.org/wiki/Todo#Optimizer_.2F_Executor

Teach the planner how to better use partial indexes for index-only scans
• http://www.postgresql.org/message-id/25141.1345072...@sss.pgh.pa.us
• 
http://www.postgresql.org/message-id/79c7d74d-59b0-4d97-a5e5-3ef29...@justatheory.com

Best,

David

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] No Index-Only Scan on Partial Index

2013-10-02 Thread Merlin Moncure
On Tuesday, October 1, 2013, David E. Wheeler da...@justatheory.com wrote:
 On Oct 1, 2013, at 3:56 PM, Merlin Moncure mmonc...@gmail.com wrote:

 I don't think it has anything to do with the conditional index -- it's
 the functional based.  For some reason postgres always wants to post
 filter (note the filter step below):

 postgres=# create index on try(upper_inf(irange));
 CREATE INDEX
 Time: 12.001 ms
 postgres=# explain select * from try where upper_inf(irange);
  QUERY PLAN

---
 Index Scan using try_upper_inf_idx on try  (cost=0.00..9.25 rows=33
width=40)
   Index Cond: (upper_inf(irange) = true)
   Filter: upper_inf(irange)

 Hrm. I get a seq scan for that query:

 create index on try(upper_inf(irange));
 explain select * from try where upper_inf(irange);
 QUERY PLAN
 ---
  Seq Scan on try  (cost=0.00..1887.00 rows=3 width=68)
Filter: upper_inf(irange)

 True also if I just select the irange. Is the filter the issue, here?

Turn off seq scan...

merlin


[HACKERS] No Index-Only Scan on Partial Index

2013-10-01 Thread David E. Wheeler
Hackers,

I was trying to figure out why a query was not doing an index-only scan on a 
partial index, when Josh Berkus pointed to this issue, reported by Merlin 
Moncure:

  
http://www.postgresql.org/message-id/CAHyXU0x1OGao48WajAfUsbXqkUDLf=_6ho6hlmb8dsfkwda...@mail.gmail.com

In short, the planner needs the column from the where clause included in the 
index to decide it can do an index-only scan. This test case demonstrates the 
truth of this finding:

CREATE TABLE try (
id INT NOT NULL,
label  TEXT NOT NULL,
active BOOLEAN DEFAULT TRUE
);

INSERT INTO try
SELECT i
 ,  (ARRAY['foo','bar','baz','wig'])[floor((random()*4))::int + 1]
 , (i % 100) = 0
  FROM generate_series(1, 10) i;

VACUUM FREEZE TRY;

CREATE INDEX idx_try_active ON try(id) WHERE active;

-- Does a bitmap heap scan.
EXPLAIN (ANALYZE, FORMAT YAML)
SELECT id FROM try WHERE active;

DROP INDEX idx_try_active;
CREATE INDEX idx_try_active ON try(label, id, active) WHERE active;

-- Does an index-only scan.
EXPLAIN (ANALYZE, FORMAT YAML)
SELECT id FROM try WHERE active;

DROP TABLE try;

The first query does a bitmap heap scan, but after the index that includes the 
active column is added, it does an index-only scan.

However, this does not quite match my case. In my case, I'm using an immutable 
function call in the index where clause:

CREATE INDEX idx_try_active ON try(id, upper_inf(irange)) WHERE 
upper_inf(irange);

I am unable to get the planner do to an index-only scan with this index no 
matter what I do. Here’s the full test case:

CREATE TABLE try (
id INT   NOT NULL,
label  TEXT  NOT NULL,
irange INT4RANGE NOT NULL
);

INSERT INTO try
SELECT i
 ,  (ARRAY['foo','bar','baz','wig'])[floor((random()*4))::int + 1]
 , int4range(1, CASE WHEN random()  0.01 THEN NULL ELSE 2 END)
  FROM generate_series(1, 10) i;

VACUUM FREEZE TRY;

CREATE INDEX idx_try_active ON try(id) WHERE upper_inf(irange);

-- Does a bitmap heap scan.
EXPLAIN (ANALYZE, FORMAT YAML)
SELECT id FROM try WHERE upper_inf(irange);

DROP INDEX idx_try_active;
CREATE INDEX idx_try_active ON try(label, id, upper_inf(irange)) WHERE 
upper_inf(irange);

-- Also does a bitmap heap scan.
EXPLAIN (ANALYZE, FORMAT YAML)
SELECT id FROM try WHERE upper_inf(irange);

DROP TABLE try;

So is there something about using a function in a conditional index that 
prevents index-only scans? Tested on 9.2 and 9.3, BTW.

Thanks,

David

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] No Index-Only Scan on Partial Index

2013-10-01 Thread Merlin Moncure
On Tue, Oct 1, 2013 at 5:35 PM, David E. Wheeler da...@justatheory.com wrote:
 Hackers,

 I was trying to figure out why a query was not doing an index-only scan on a 
 partial index, when Josh Berkus pointed to this issue, reported by Merlin 
 Moncure:

   
 http://www.postgresql.org/message-id/CAHyXU0x1OGao48WajAfUsbXqkUDLf=_6ho6hlmb8dsfkwda...@mail.gmail.com

 In short, the planner needs the column from the where clause included in the 
 index to decide it can do an index-only scan. This test case demonstrates the 
 truth of this finding:

 CREATE TABLE try (
 id INT NOT NULL,
 label  TEXT NOT NULL,
 active BOOLEAN DEFAULT TRUE
 );

 INSERT INTO try
 SELECT i
  ,  (ARRAY['foo','bar','baz','wig'])[floor((random()*4))::int + 1]
  , (i % 100) = 0
   FROM generate_series(1, 10) i;

 VACUUM FREEZE TRY;

 CREATE INDEX idx_try_active ON try(id) WHERE active;

 -- Does a bitmap heap scan.
 EXPLAIN (ANALYZE, FORMAT YAML)
 SELECT id FROM try WHERE active;

 DROP INDEX idx_try_active;
 CREATE INDEX idx_try_active ON try(label, id, active) WHERE active;

 -- Does an index-only scan.
 EXPLAIN (ANALYZE, FORMAT YAML)
 SELECT id FROM try WHERE active;

 DROP TABLE try;

 The first query does a bitmap heap scan, but after the index that includes 
 the active column is added, it does an index-only scan.

 However, this does not quite match my case. In my case, I'm using an 
 immutable function call in the index where clause:

 CREATE INDEX idx_try_active ON try(id, upper_inf(irange)) WHERE 
 upper_inf(irange);

 I am unable to get the planner do to an index-only scan with this index no 
 matter what I do. Here’s the full test case:

 CREATE TABLE try (
 id INT   NOT NULL,
 label  TEXT  NOT NULL,
 irange INT4RANGE NOT NULL
 );

 INSERT INTO try
 SELECT i
  ,  (ARRAY['foo','bar','baz','wig'])[floor((random()*4))::int + 1]
  , int4range(1, CASE WHEN random()  0.01 THEN NULL ELSE 2 END)
   FROM generate_series(1, 10) i;

 VACUUM FREEZE TRY;

 CREATE INDEX idx_try_active ON try(id) WHERE upper_inf(irange);

 -- Does a bitmap heap scan.
 EXPLAIN (ANALYZE, FORMAT YAML)
 SELECT id FROM try WHERE upper_inf(irange);

 DROP INDEX idx_try_active;
 CREATE INDEX idx_try_active ON try(label, id, upper_inf(irange)) WHERE 
 upper_inf(irange);

 -- Also does a bitmap heap scan.
 EXPLAIN (ANALYZE, FORMAT YAML)
 SELECT id FROM try WHERE upper_inf(irange);

 DROP TABLE try;

 So is there something about using a function in a conditional index that 
 prevents index-only scans? Tested on 9.2 and 9.3, BTW.

I don't think it has anything to do with the conditional index -- it's
the functional based.  For some reason postgres always wants to post
filter (note the filter step below):

postgres=# create index on try(upper_inf(irange));
CREATE INDEX
Time: 12.001 ms
postgres=# explain select * from try where upper_inf(irange);
  QUERY PLAN
---
 Index Scan using try_upper_inf_idx on try  (cost=0.00..9.25 rows=33 width=40)
   Index Cond: (upper_inf(irange) = true)
   Filter: upper_inf(irange)

merlin


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] No Index-Only Scan on Partial Index

2013-10-01 Thread David E. Wheeler
On Oct 1, 2013, at 3:56 PM, Merlin Moncure mmonc...@gmail.com wrote:

 I don't think it has anything to do with the conditional index -- it's
 the functional based.  For some reason postgres always wants to post
 filter (note the filter step below):
 
 postgres=# create index on try(upper_inf(irange));
 CREATE INDEX
 Time: 12.001 ms
 postgres=# explain select * from try where upper_inf(irange);
  QUERY PLAN
 ---
 Index Scan using try_upper_inf_idx on try  (cost=0.00..9.25 rows=33 width=40)
   Index Cond: (upper_inf(irange) = true)
   Filter: upper_inf(irange)

Hrm. I get a seq scan for that query:

create index on try(upper_inf(irange));
explain select * from try where upper_inf(irange);
QUERY PLAN 
---
 Seq Scan on try  (cost=0.00..1887.00 rows=3 width=68)
   Filter: upper_inf(irange)

True also if I just select the irange. Is the filter the issue, here?

Best,

David



-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers