Received: from maia.hub.org (maia-3.hub.org [200.46.204.243]) by mail.postgresql.org (Postfix) with ESMTP id 8D4051337BD2 for ; Tue, 5 Apr 2011 19:36:09 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.243]) (amavisd-maia, port 10024) with ESMTP id 38231-05 for ; Tue, 5 Apr 2011 22:36:02 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from smtp1.linux-foundation.org (smtp1.linux-foundation.org [140.211.169.13]) by mail.postgresql.org (Postfix) with ESMTP id C2C1B1337C04 for ; Tue, 5 Apr 2011 19:36:01 -0300 (ADT) Received: from mail-px0-f174.google.com (mail-px0-f174.google.com [209.85.212.174]) (authenticated bits=0) by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id p35MZxie001204 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=FAIL) for ; Tue, 5 Apr 2011 15:35:59 -0700 Received: by pxi15 with SMTP id 15so470062pxi.33 for ; Tue, 05 Apr 2011 15:35:59 -0700 (PDT) Received: by 10.142.162.13 with SMTP id k13mr181266wfe.337.1302042959280; Tue, 05 Apr 2011 15:35:59 -0700 (PDT) MIME-Version: 1.0 Received: by 10.68.40.199 with HTTP; Tue, 5 Apr 2011 15:35:29 -0700 (PDT) From: Thom Brown Date: Tue, 5 Apr 2011 23:35:29 +0100 Message-ID: Subject: Partial index slower than regular index To: pgsql-performance Content-Type: text/plain; charset=ISO-8859-1 X-MIMEDefang-Filter: lf$Revision: 1.188 $ X-Scanned-By: MIMEDefang 2.63 on 140.211.169.13 X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.9 tagged_above=-10 required=5 tests=BAYES_00=-1.9 X-Spam-Level: X-Archive-Number: 201104/33 X-Sequence-Number: 43095 I'm using 9.1dev. Could someone explain the following behaviour? -- create a test table CREATE TABLE indextest (id serial, stuff text); -- insert loads of values with intermittent sets of less common values INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); INSERT INTO indextest (stuff) SELECT 'meow' FROM generate_series (1,1000000); INSERT INTO indextest (stuff) SELECT 'bark' FROM generate_series (1,1000); -- create regular index CREATE INDEX indextest_stuff ON indextest(stuff); -- update table stats ANALYZE indextest; postgres=# explain analyze select * from indextest where stuff = 'bark'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------- Index Scan using indextest_stuff on indextest (cost=0.00..485.09 rows=9076 width=9) (actual time=0.142..3.533 rows=8000 loops=1) Index Cond: (stuff = 'bark'::text) Total runtime: 4.248 ms (3 rows) This is very fast. Now if I drop the index and add a partial index with the conditions being tested. DROP INDEX indextest_stuff; CREATE INDEX indextest_stuff ON indextest(stuff) WHERE stuff = 'bark'; postgres=# explain analyze select * from indextest where stuff = 'bark'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Seq Scan on indextest (cost=0.00..143386.48 rows=5606 width=9) (actual time=164.321..1299.794 rows=8000 loops=1) Filter: (stuff = 'bark'::text) Total runtime: 1300.267 ms (3 rows) The index doesn't get used. There's probably a logical explanation, which is what I'm curious about. -- Thom Brown Twitter: @darkixion IRC (freenode): dark_ixion Registered Linux user: #516935 EnterpriseDB UK: http://www.enterprisedb.com The Enterprise PostgreSQL Company1