Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1h6nnq-0004T4-0b for pgsql-performance@arkaria.postgresql.org; Thu, 21 Mar 2019 02:51:34 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1h6nno-0004rX-Br for pgsql-performance@arkaria.postgresql.org; Thu, 21 Mar 2019 02:51:32 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1h6nnn-0004kZ-RE for pgsql-performance@lists.postgresql.org; Thu, 21 Mar 2019 02:51:32 +0000 Received: from gproxy7-pub.mail.unifiedlayer.com ([70.40.196.235]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1h6nnf-0001UV-VK for pgsql-performance@postgresql.org; Thu, 21 Mar 2019 02:51:30 +0000 Received: from cmgw10.unifiedlayer.com (unknown [10.9.0.10]) by gproxy7.mail.unifiedlayer.com (Postfix) with ESMTP id DAC102171D3 for ; Wed, 20 Mar 2019 20:45:14 -0600 (MDT) Received: from host214.hostmonster.com ([74.220.215.214]) by cmsmtp with ESMTP id 6nhihxjXouj2o6nhihxW1M; Wed, 20 Mar 2019 20:45:14 -0600 X-Authority-Reason: nr=8 X-Authority-Analysis: $(_cmae_reason DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=pragmaticdata.com; s=default; h=Content-Type:MIME-Version:Date:Message-ID: Subject:From:To:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=6yX5WP3u3Z38SNN+N6rk4GcDnbhP5jUTMdEwrekXI6E=; b=eZYIdeqnA6arc7oLcO0EcNW5Ab x6r4PqVzbom65Ny9CDdc3d0KCOJIgHA62v31nrrjrtnP4Of61dnpz/gfm6wiF1/x2B83mxgSjxx7u I2vV26DakXixi/iAXwFCwAX/I; Received: from [191.7.153.218] (port=57830 helo=[192.168.9.9]) by host214.hostmonster.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1h6nhi-001Rux-11 for pgsql-performance@postgresql.org; Wed, 20 Mar 2019 20:45:14 -0600 To: "pgsql-performance." From: Gunther Subject: Poor man's partitioned index .... not being used? Message-ID: Date: Wed, 20 Mar 2019 22:45:07 -0400 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.5.3 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="------------D0B0337050F0DDF83BEBB707" Content-Language: en-US X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - host214.hostmonster.com X-AntiAbuse: Original Domain - postgresql.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - gusw.net X-BWhitelist: no X-Source-IP: 191.7.153.218 X-Source-L: No X-Exim-ID: 1h6nhi-001Rux-11 X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: ([192.168.9.9]) [191.7.153.218]:57830 X-Source-Auth: gunther+pragmaticdata.com X-Email-Count: 1 X-Source-Cap: cHJhZ21hdDE7cHJhZ21hdDE7aG9zdDIxNC5ob3N0bW9uc3Rlci5jb20= X-Local-Domain: yes List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------D0B0337050F0DDF83BEBB707 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Hi all, look at this short story please: foo=# CREATE TABLE Test(id int NOT NULL PRIMARY KEY); CREATE TABLE foo=# INSERT INTO test SELECT row_number() OVER() FROM pg_class a CROSS JOIN pg_class b; INSERT 0 388129 foo=# EXPLAIN SELECT * FROM Test WHERE id = '8934'; QUERY PLAN --------------------------------------------------------------------------- Index Only Scan using test_pkey on test (cost=0.42..8.44 rows=1 width=4) Index Cond: (id = 8934) (2 rows) foo=# ALTER TABLE Test DROP CONSTRAINT Test_pkey; ALTER TABLE foo=# EXPLAIN SELECT * FROM Test WHERE id = '8934';  QUERY PLAN ------------------------------------------------------- Seq Scan on test (cost=0.00..6569.61 rows=1 width=4) Filter: (id = 8934) (2 rows) foo=# SELECT max(id)/2 FROM Test; ?column? ---------- 194064 (1 row) foo=# CREATE UNIQUE INDEX Test_pk0 ON Test(id) WHERE id < 194064; CREATE INDEX foo=# CREATE UNIQUE INDEX Test_pk1 ON Test(id) WHERE id >= 194064; CREATE INDEX foo=# ANALYZE Test; ANALYZE foo=# EXPLAIN SELECT * FROM Test WHERE id = 8934; QUERY PLAN -------------------------------------------------------------------------- Index Only Scan using test_pk0 on test (cost=0.42..8.44 rows=1 width=4) Index Cond: (id = 8934) (2 rows) foo=# DROP INDEX Test_pk0; DROP INDEX foo=# DROP INDEX Test_pk1; DROP INDEX foo=# CREATE UNIQUE INDEX Test_pk0 ON Test(id) WHERE mod(id,2) = 0; CREATE INDEX foo=# CREATE UNIQUE INDEX Test_pk1 ON Test(id) WHERE mod(id,2) = 1; CREATE INDEX foo=# ANALYZE Test; ANALYZE foo=# EXPLAIN SELECT * FROM Test WHERE id = '8934'; QUERY PLAN ------------------------------------------------------- Seq Scan on test (cost=0.00..6569.61 rows=1 width=4) Filter: (id = 8934) (2 rows) Why is that index never used? PS: there is a performance question behind this, big table, heavily used index, the hope was that with this simple scheme of partitioning just the index one might distribute the load better. I know, if the load really is so big, why not partition the entire table. But just for hecks, why not this way? regards, -Gunther --------------D0B0337050F0DDF83BEBB707 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit
Hi all, look at this short story please:

foo=# CREATE TABLE Test(id int NOT NULL PRIMARY KEY);
CREATE TABLE
foo=# INSERT INTO test SELECT row_number() OVER() FROM pg_class a CROSS JOIN pg_class b;
INSERT 0 388129
foo=# EXPLAIN SELECT * FROM Test WHERE id = '8934';
                                QUERY PLAN
---------------------------------------------------------------------------
 Index Only Scan using test_pkey on test  (cost=0.42..8.44 rows=1 width=4)
   Index Cond: (id = 8934)
(2 rows)

foo=# ALTER TABLE Test DROP CONSTRAINT Test_pkey;
ALTER TABLE
foo=# EXPLAIN SELECT * FROM Test WHERE id = '8934';
                       QUERY PLAN
-------------------------------------------------------
 Seq Scan on test  (cost=0.00..6569.61 rows=1 width=4)
   Filter: (id = 8934)
(2 rows)

foo=# SELECT max(id)/2 FROM Test;
 ?column?
----------
   194064
(1 row)

foo=# CREATE UNIQUE INDEX Test_pk0 ON Test(id) WHERE id < 194064;
CREATE INDEX
foo=# CREATE UNIQUE INDEX Test_pk1 ON Test(id) WHERE id >= 194064;
CREATE INDEX
foo=# ANALYZE Test;
ANALYZE
foo=# EXPLAIN SELECT * FROM Test WHERE id = 8934;
                                QUERY PLAN
--------------------------------------------------------------------------
 Index Only Scan using test_pk0 on test  (cost=0.42..8.44 rows=1 width=4)
   Index Cond: (id = 8934)
(2 rows)


foo=# DROP INDEX Test_pk0;
DROP INDEX
foo=# DROP INDEX Test_pk1;
DROP INDEX

foo=# CREATE UNIQUE INDEX Test_pk0 ON Test(id) WHERE mod(id,2) = 0;
CREATE INDEX
foo=# CREATE UNIQUE INDEX Test_pk1 ON Test(id) WHERE mod(id,2) = 1;
CREATE INDEX
foo=# ANALYZE Test;
ANALYZE
foo=# EXPLAIN SELECT * FROM Test WHERE id = '8934';    
                  QUERY PLAN
-------------------------------------------------------
 Seq Scan on test  (cost=0.00..6569.61 rows=1 width=4)
   Filter: (id = 8934)
(2 rows)

Why is that index never used?

PS: there is a performance question behind this, big table, heavily used index, 
the hope was that with this simple scheme of partitioning just the index one might
distribute the load better. I know, if the load really is so big, why not partition
the entire table. But just for hecks, why not this way?

regards,
-Gunther

--------------D0B0337050F0DDF83BEBB707--