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 1i0n6B-0005fU-HN for pgsql-performance@arkaria.postgresql.org; Thu, 22 Aug 2019 13:25:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1i0n69-0001LH-In for pgsql-performance@arkaria.postgresql.org; Thu, 22 Aug 2019 13:25:53 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i0n69-0001Ds-3h for pgsql-performance@lists.postgresql.org; Thu, 22 Aug 2019 13:25:53 +0000 Received: from mout.perfora.net ([74.208.4.194]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.92) (envelope-from ) id 1i0n61-0004on-SV for pgsql-performance@lists.postgresql.org; Thu, 22 Aug 2019 13:25:51 +0000 Received: from [192.168.1.101] ([98.169.208.73]) by mrelay.perfora.net (mreueus001 [74.208.5.2]) with ESMTPSA (Nemesis) id 0MKrvq-1i0n5w2Qi0-0008Ck; Thu, 22 Aug 2019 15:25:40 +0200 Subject: Re: Extremely slow count (simple query, with index) To: Marco Colli Cc: pgsql-performance@lists.postgresql.org References: From: MichaelDBA Message-ID: <02a535cc-ad71-2380-e15a-cf6123fb65d7@sqlexec.com> Date: Thu, 22 Aug 2019 09:25:36 -0400 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 PostboxApp/6.1.18 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/alternative; boundary="------------8D709458648131B9FE380F31" Content-Language: en-US X-Provags-ID: V03:K1:oixLJw5/VcY85aoM77m6eG4GbTAF3FhWlMzcx58H+TMlinIqI+x T9GLwmx+SlV4raIkjhbeH8K57OPSdor28kkoLie0kEhl++Tx+VvMJTPCysbqGo5rXtBj5At xe0qSs8f8ww/JebMr1oEeIgYaCJch9uC03u1DuJc+VCDcidZTTB54o8cqU7tbT4mGGnpF7P jQZXDsnWmZPHllUKNo3Og== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:dEL9VfCchTA=:alj4XPvJCtLcfFYBunHir0 aH47tEaj6M50JIryXKoNRmFlpO4Fzr/Rzo4zjNkESzpjyCdHr77OoWsBgJgpWePbBNYz9OPug uj7+i1XWpuWUV78fq7YxztviOVaEnu2CXk5gf99bLMLhA847scbzQLxSVDTT/7mcoOKXeKQ1+ 6QkLvy/Zmhytp+H5ZIlTnnIO1SnL5w0sblwkIwkJHM1uafYbAcxdkyVUSVwjAVyxZH1KcAEzy 1juHFqkh5OUqVszHERmF8CfAFd93Kz7mNRHVLGI9VxOpa7a7QXv+lHtOSd00/gyEaMt1GL0D1 CBIcQm+YBjKWEPA/Lw+TPuq45XuG2t6r+La4P98bCQMwy36wB5qyOKhhz2DbBAddML10KhgUf 4RJd2hIu+7IKfMOkr7Pcph/eFTxjX+QCcp+HDq5nDJ8EMVLvVBKJ44Sj+4F5bB1PsToUuovGG 2K7O0GarwSiL2xTI5OcbWjAL0gqmnIyegZ4kkEwJPE5yNwPlzycGdYLGJ6cFscHW1Qepr+kav 0WxkfytCyMqapLh18hvERCCk/1EyH3p2cNaO/CH8+QOeLDZur0nHLCRjbA0Ec/jXXFNlNHWJY eduayIJrUOBIS4RM2YJI07ELNId3XFYmUyz9wuF7+u6OgITySNR7/ySM19AePiZGz+jELFPrV rIiPypxDAcdMitFiADVAn105gNuxEzKQnJ4zgz+uctgubKb194jxVnE4TmDZeILJm+3AIvvG3 ugI7OY+WVx12M9pFrhCfKthAy3OR9mewCdAiDEFbwKR0+3w7CtBPJxb7Vb8= List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------8D709458648131B9FE380F31 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Hi Marco, Since you said approximates would be good enough, there are two ways to do that.  Query pg_class.reltuples or pg_stat_user_tables.n_live_tup. Personally, I prefer the pg_stat_user tables since it is more current than pg_class table, unless you run ANALYZE on your target table before querying pg_class table.  Then of course you get results in a few milliseconds since you do not incur the tablescan cost of selecting directly from the target table. Regards, Michael Vitale Marco Colli wrote on 8/22/2019 8:44 AM: > Hello! > > Any help would be greatly appreciated. > I need to run these simple queries on a table with millions of rows: > > ``` > SELECT COUNT(*) FROM "subscriptions" WHERE > "subscriptions"."project_id" = 123; > ``` > > ``` > SELECT COUNT(*) FROM "subscriptions" WHERE > "subscriptions"."project_id" = 123 AND "subscriptions"."trashed_at" IS > NULL; > ``` > > The count result for both queries, for project 123, is about 5M. > > I have an index in place on `project_id`, and also another index on > `(project_id, trashed_at)`: > > ``` > "index_subscriptions_on_project_id_and_created_at" btree (project_id, > created_at DESC) > "index_subscriptions_on_project_id_and_trashed_at" btree (project_id, > trashed_at DESC) > ``` > > The problem is that both queries are extremely slow and take about 17s > each. > > These are the results of `EXPLAIN ANALIZE`: > > > ``` > QUERY PLAN > -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- >  Aggregate  (cost=2068127.29..2068127.30 rows=1 width=0) (actual > time=17342.420..17342.420 rows=1 loops=1) >    ->  Bitmap Heap Scan on subscriptions  (cost=199573.94..2055635.23 > rows=4996823 width=0) (actual time=1666.409..16855.610 rows=4994254 > loops=1) >        Recheck Cond: (project_id = 123) >          Rows Removed by Index Recheck: 23746378 >          Heap Blocks: exact=131205 lossy=1480411 >          ->  Bitmap Index Scan on > index_subscriptions_on_project_id_and_trashed_at >  (cost=0.00..198324.74 rows=4996823 width=0) (actual > time=1582.717..1582.717 rows=4994877 loops=1) >                Index Cond: (project_id = 123) >  Planning time: 0.090 ms >  Execution time: 17344.182 ms > (9 rows) > ``` > > > ``` >     QUERY PLAN > -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- >  Aggregate  (cost=2047881.69..2047881.70 rows=1 width=0) (actual > time=17557.218..17557.218 rows=1 loops=1) >    ->  Bitmap Heap Scan on subscriptions  (cost=187953.70..2036810.19 > rows=4428599 width=0) (actual time=1644.966..17078.378 rows=4994130 > loops=1) >        Recheck Cond: ((project_id = 123) AND (trashed_at IS NULL)) >        Rows Removed by Index Recheck: 23746273 >          Heap Blocks: exact=131144 lossy=1480409 >          ->  Bitmap Index Scan on > index_subscriptions_on_project_id_and_trashed_at >  (cost=0.00..186846.55 rows=4428599 width=0) (actual > time=1566.163..1566.163 rows=4994749 loops=1) >  Index Cond: ((project_id = 123) AND (trashed_at IS NULL)) >  Planning time: 0.084 ms >  Execution time: 17558.522 ms > (9 rows) > ``` > > What is the problem? > What can I do to improve the performance (i.e. count in a few seconds)? > > I have also tried to increase work_mem from 16MB to 128MB without any > improvement. > Even an approximate count would be enough. > Postgresql v9.5 > --------------8D709458648131B9FE380F31 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit Hi Marco,

Since you said approximates would be good enough, there are two ways to do that.  Query pg_class.reltuples or pg_stat_user_tables.n_live_tup.  Personally, I prefer the pg_stat_user tables since it is more current than pg_class table, unless you run ANALYZE on your target table before querying pg_class table.  Then of course you get results in a few milliseconds since you do not incur the tablescan cost of selecting directly from the target table.

Regards,
Michael Vitale


Marco Colli wrote on 8/22/2019 8:44 AM:
Hello!

Any help would be greatly appreciated.
I need to run these simple queries on a table with millions of rows:

```
SELECT COUNT(*) FROM "subscriptions" WHERE "subscriptions"."project_id" = 123;
```

```
SELECT COUNT(*) FROM "subscriptions" WHERE "subscriptions"."project_id" = 123 AND "subscriptions"."trashed_at" IS NULL;
```

The count result for both queries, for project 123, is about 5M.

I have an index in place on `project_id`, and also another index on `(project_id, trashed_at)`:

```
"index_subscriptions_on_project_id_and_created_at" btree (project_id, created_at DESC)
"index_subscriptions_on_project_id_and_trashed_at" btree (project_id, trashed_at DESC)
```

The problem is that both queries are extremely slow and take about 17s each.

These are the results of `EXPLAIN ANALIZE`:


```
      QUERY PLAN                                                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=2068127.29..2068127.30 rows=1 width=0) (actual time=17342.420..17342.420 rows=1 loops=1)
   ->  Bitmap Heap Scan on subscriptions  (cost=199573.94..2055635.23 rows=4996823 width=0) (actual time=1666.409..16855.610 rows=4994254 loops=1)
         Recheck Cond: (project_id = 123)
         Rows Removed by Index Recheck: 23746378
         Heap Blocks: exact=131205 lossy=1480411
         ->  Bitmap Index Scan on index_subscriptions_on_project_id_and_trashed_at  (cost=0.00..198324.74 rows=4996823 width=0) (actual time=1582.717..1582.717 rows=4994877 loops=1)
               Index Cond: (project_id = 123)
 Planning time: 0.090 ms
 Execution time: 17344.182 ms
(9 rows)
```


```
      QUERY PLAN                                                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=2047881.69..2047881.70 rows=1 width=0) (actual time=17557.218..17557.218 rows=1 loops=1)
   ->  Bitmap Heap Scan on subscriptions  (cost=187953.70..2036810.19 rows=4428599 width=0) (actual time=1644.966..17078.378 rows=4994130 loops=1)
         Recheck Cond: ((project_id = 123) AND (trashed_at IS NULL))
         Rows Removed by Index Recheck: 23746273
         Heap Blocks: exact=131144 lossy=1480409
         ->  Bitmap Index Scan on index_subscriptions_on_project_id_and_trashed_at  (cost=0.00..186846.55 rows=4428599 width=0) (actual time=1566.163..1566.163 rows=4994749 loops=1)
               Index Cond: ((project_id = 123) AND (trashed_at IS NULL))
 Planning time: 0.084 ms
 Execution time: 17558.522 ms
(9 rows)
```

What is the problem? 
What can I do to improve the performance (i.e. count in a few seconds)?

I have also tried to increase work_mem from 16MB to 128MB without any improvement.
Even an approximate count would be enough.
Postgresql v9.5


--------------8D709458648131B9FE380F31--