Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lEtvx-00020h-Ts for pgsql-performance@arkaria.postgresql.org; Wed, 24 Feb 2021 13:10:30 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1lEtvw-0002iM-RS for pgsql-performance@arkaria.postgresql.org; Wed, 24 Feb 2021 13:10:28 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lEtvv-0002i4-G0 for pgsql-performance@lists.postgresql.org; Wed, 24 Feb 2021 13:10:28 +0000 Received: from gateway23.websitewelcome.com ([192.185.50.107]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lEtvs-0006ix-AI for pgsql-performance@lists.postgresql.org; Wed, 24 Feb 2021 13:10:25 +0000 Received: from cm10.websitewelcome.com (cm10.websitewelcome.com [100.42.49.4]) by gateway23.websitewelcome.com (Postfix) with ESMTP id 9541328DDA for ; Wed, 24 Feb 2021 07:10:23 -0600 (CST) Received: from host2097.hostmonster.com ([67.20.114.243]) by cmsmtp with SMTP id EtvqlZ1mouDoAEtvqlPnl2; Wed, 24 Feb 2021 07:10:23 -0600 X-Authority-Reason: nr=8 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=schadow.us; s=default; h=Content-Type:In-Reply-To:MIME-Version:Date:Message-ID:From: References:To:Subject:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID :Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To: Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe :List-Post:List-Owner:List-Archive; bh=tDdW3HYaUgoLT7dsmsJWGetiMKmfMKWDTTRdRPCq/S4=; b=nXwEFSfdc+jzPW4D+i+D6Qlwa1 sjlkKiZeTfhukm2A4GezNbUc9gO4Vd/JPu2++lWd5m3Q14D/OAViQiapsA/xjL47Jdj5eItnq8qgK R9vLbmDCXTkoLZzykuBVQRvJc; Received: from [189.120.73.125] (port=33560 helo=[192.168.0.46]) by host2097.hostmonster.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1lEtvq-000T2Y-19 for pgsql-performance@lists.postgresql.org; Wed, 24 Feb 2021 06:10:22 -0700 Subject: Re: Postgres performance comparing GCP and AWS To: pgsql-performance@lists.postgresql.org References: From: Gunther Schadow Message-ID: <3dcfe362-b9fd-5168-863d-ef5651b74a71@gusw.net> Date: Wed, 24 Feb 2021 08:10:20 -0500 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.7.1 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/alternative; boundary="------------4D75A144FFF51D2F20F412A7" Content-Language: en-US X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - host2097.hostmonster.com X-AntiAbuse: Original Domain - lists.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: 189.120.73.125 X-Source-L: No X-Exim-ID: 1lEtvq-000T2Y-19 X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: ([192.168.0.46]) [189.120.73.125]:33560 X-Source-Auth: ebiz+schadow.us X-Email-Count: 1 X-Source-Cap: cHJhZ21hdDE7cHJhZ21hdDE7aG9zdDIwOTcuaG9zdG1vbnN0ZXIuY29t 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. --------------4D75A144FFF51D2F20F412A7 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Hi Maurici, in my experience the key factor about speed in big queries is sequential scan. There is a huge variance in how the system is tuned. In some cases I cannot read more than 10 MB/s, in others I get to expect 20-40 MB/s. But then, when things are tuned well and the parallel workers set in, I see the throughput spike to 100-200 MB/s. You may have to enable the parallel workers in your postgresql.conf So, to me, this is what you want to check first. While the query runs, have both iostat and top running, with top -j or -c or -a or whatever it is on that particular OS to see the detail info about the process. Perhaps even -H to see threads. Then you should see good flow with high read speed and reasonable CPU load %. If you get low read speed and low CPU that is a sign of IO blockage somewhere. If you get high CPU and low IO, that's a planning mistake (the nested loop trap). You don't have that here apparently. But index scans I have seen with much worse IO throughput than seq table scans. Not sure. Also, on AWS you need to be sure you have enough IOPS provisioned on your EBS (I use gp3 now where you can have up to 10k IOPS) and also check bus throughput of the EC2 instance. Needless to say you don't want a t* instance where you have a limited burst CPU capacity only. regards, -Gunther On 2/23/2021 1:12 PM, Maurici Meneghetti wrote: > Hi everyone, > > I have 2 postgres instances created from the same dump (backup), one > on a GCP VM and the other on AWS RDS. The first instance takes 18 > minutes and the second one takes less than 20s to run this simples query: > SELECT "Id", "DateTime", "SignalRegisterId", "Raw" FROM > "SignalRecordsBlobs" WHERE "SignalSettingId" = 103 AND "DateTime" > BETWEEN '2019-11-28T14:00:12.540200000' AND > '2020-07-23T21:12:32.249000000'; > I’ve run this query a few times to make sure both should be reading > data from cache. > I expect my postgres on GPC to be at least similar to the one managed > by AWS RDS so that I can work on improvements parallelly and compare. > > *DETAILS: > Query explain for Postgres on GCP VM: > *Bitmap Heap Scan on SignalRecordsBlobs SignalRecordsBlobs >  (cost=18.80..2480.65 rows=799 width=70) (actual time=216.766..776.032 > rows=5122 loops=1) >     Filter: (("DateTime" >= \'2019-11-28 14:00:12.5402\'::timestamp > without time zone) AND ("DateTime" <= \'2020-07-23 > 21:12:32.249\'::timestamp without time zone)) >     Heap Blocks: exact=5223 >     Buffers: shared hit=423 read=4821 >   ->  Bitmap Index Scan on IDX_SignalRecordsBlobs_SignalSettingId >  (cost=0.00..18.61 rows=824 width=0) (actual time=109.000..109.001 > rows=5228 loops=1) >           Index Cond: ("SignalSettingId" = 103) >           Buffers: shared hit=3 read=18 > Planning time: 456.315 ms > Execution time: 776.976 ms > > *Query explain for Postgres on AWS RDS: > *Bitmap Heap Scan on SignalRecordsBlobs SignalRecordsBlobs >  (cost=190.02..13204.28 rows=6213 width=69) (actual time=2.215..14.505 > rows=5122 loops=1) >     Filter: (("DateTime" >= \'2019-11-28 14:00:12.5402\'::timestamp > without time zone) AND ("DateTime" <= \'2020-07-23 > 21:12:32.249\'::timestamp without time zone)) >     Heap Blocks: exact=5209 >     Buffers: shared hit=3290 read=1948 >   ->  Bitmap Index Scan on IDX_SignalRecordsBlobs_SignalSettingId >  (cost=0.00..188.46 rows=6405 width=0) (actual time=1.159..1.159 > rows=5228 loops=1) >           Index Cond: ("SignalSettingId" = 103) >           Buffers: shared hit=3 read=26 > Planning time: 0.407 ms > Execution time: 14.87 ms > > *PostgreSQL version number running: > • VM on GCP*: PostgreSQL 11.10 (Debian 11.10-0+deb10u1) on > x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit > *• Managed by RDS on AWS:* PostgreSQL 11.10 on x86_64-pc-linux-gnu, > compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11), 64-bit > > *How PostgreSQL was installed: > • VM on GCP*: Already installed when created VM running Debian on > Google Console. > *• Managed by RDS on AWS:* RDS managed the installation. > > *Changes made to the settings in the postgresql.conf file: > *Here are some postgres parameters that might be useful: > *Instance on VM on GCP (2 vCPUs, 2 GB memory, 800 GB disk):* > • effective_cache_size: 1496MB > • maintenance_work_mem: 255462kB (close to 249MB) > • max_wal_size: 1GB > • min_wal_size: 512MB > • shared_buffers: 510920kB (close to 499MB) > • max_locks_per_transaction 1000 > • wal_buffers: 15320kB (close to 15MB) > • work_mem: 2554kB > • effective_io_concurrency: 200 > • dynamic_shared_memory_type: posix > On this instance we installed a postgres extension called timescaledb > to gain performance on other tables. Some of these parameters were set > using recommendations from that extension. > > *Instance managed by RDS (2 vCPUs, 2 GiB RAM, 250GB disk, 750 de IOPS):* > • effective_cache_size: 1887792kB (close to 1844MB) > • maintenance_work_mem: 64MB > • max_wal_size: 2GB > • min_wal_size: 192MB > • shared_buffers: 943896kB (close to 922MB) > • max_locks_per_transaction 64 > > *Operating system and version by runing "uname -a": > • VM on GCP:* Linux {{{my instance name}}} 4.19.0-14-cloud-amd64 #1 > SMP Debian 4.19.171-2 (2021-01-30) x86_64 GNU/Linux > *• Managed by AWS RDS:* Aparently Red Hay as shown using SELECT version(); > > *Program used to connect to PostgreSQL:* Python psycopg2.connect() to > create the connection and pandas read_sql_query() to query using that > connection. > > Thanks in advance --------------4D75A144FFF51D2F20F412A7 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit

Hi Maurici,

in my experience the key factor about speed in big queries is sequential scan. There is a huge variance in how the system is tuned. In some cases I cannot read more than 10 MB/s, in others I get to expect 20-40 MB/s. But then, when things are tuned well and the parallel workers set in, I see the throughput spike to 100-200 MB/s.

You may have to enable the parallel workers in your postgresql.conf

So, to me, this is what you want to check first. While the query runs, have both iostat and top running, with top -j or -c or -a or whatever it is on that particular OS to see the detail info about the process. Perhaps even -H to see threads.

Then you should see good flow with high read speed and reasonable CPU load %. If you get low read speed and low CPU that is a sign of IO blockage somewhere. If you get high CPU and low IO, that's a planning mistake (the nested loop trap). You don't have that here apparently. But index scans I have seen with much worse IO throughput than seq table scans. Not sure.

Also, on AWS you need to be sure you have enough IOPS provisioned on your EBS (I use gp3 now where you can have up to 10k IOPS) and  also check bus throughput of the EC2 instance. Needless to say you don't want a t* instance where you have a limited burst CPU capacity only.

regards,
-Gunther

On 2/23/2021 1:12 PM, Maurici Meneghetti wrote:
Hi everyone,

I have 2 postgres instances created from the same dump (backup), one on a GCP VM and the other on AWS RDS. The first instance takes 18 minutes and the second one takes less than 20s to run this simples query:
SELECT "Id", "DateTime", "SignalRegisterId", "Raw" FROM "SignalRecordsBlobs" WHERE "SignalSettingId" = 103 AND "DateTime" BETWEEN '2019-11-28T14:00:12.540200000' AND '2020-07-23T21:12:32.249000000';
I’ve run this query a few times to make sure both should be reading data from cache.
I expect my postgres on GPC to be at least similar to the one managed by AWS RDS so that I can work on improvements parallelly and compare.

DETAILS:
Query explain for Postgres on GCP VM:
Bitmap Heap Scan on SignalRecordsBlobs SignalRecordsBlobs  (cost=18.80..2480.65 rows=799 width=70) (actual time=216.766..776.032 rows=5122 loops=1)
    Filter: (("DateTime" >= \'2019-11-28 14:00:12.5402\'::timestamp without time zone) AND ("DateTime" <= \'2020-07-23 21:12:32.249\'::timestamp without time zone))
    Heap Blocks: exact=5223
    Buffers: shared hit=423 read=4821
  ->  Bitmap Index Scan on IDX_SignalRecordsBlobs_SignalSettingId  (cost=0.00..18.61 rows=824 width=0) (actual time=109.000..109.001 rows=5228 loops=1)
          Index Cond: ("SignalSettingId" = 103)
          Buffers: shared hit=3 read=18
Planning time: 456.315 ms
Execution time: 776.976 ms

Query explain for Postgres on AWS RDS:
Bitmap Heap Scan on SignalRecordsBlobs SignalRecordsBlobs  (cost=190.02..13204.28 rows=6213 width=69) (actual time=2.215..14.505 rows=5122 loops=1)
    Filter: (("DateTime" >= \'2019-11-28 14:00:12.5402\'::timestamp without time zone) AND ("DateTime" <= \'2020-07-23 21:12:32.249\'::timestamp without time zone))
    Heap Blocks: exact=5209
    Buffers: shared hit=3290 read=1948
  ->  Bitmap Index Scan on IDX_SignalRecordsBlobs_SignalSettingId  (cost=0.00..188.46 rows=6405 width=0) (actual time=1.159..1.159 rows=5228 loops=1)
          Index Cond: ("SignalSettingId" = 103)
          Buffers: shared hit=3 read=26
Planning time: 0.407 ms
Execution time: 14.87 ms

PostgreSQL version number running:
• VM on GCP
: PostgreSQL 11.10 (Debian 11.10-0+deb10u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
• Managed by RDS on AWS: PostgreSQL 11.10 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11), 64-bit

How PostgreSQL was installed:
• VM on GCP
: Already installed when created VM running Debian on Google Console.
• Managed by RDS on AWS: RDS managed the installation.

Changes made to the settings in the postgresql.conf file:
Here are some postgres parameters that might be useful:
Instance on VM on GCP (2 vCPUs, 2 GB memory, 800 GB disk):
• effective_cache_size: 1496MB
• maintenance_work_mem: 255462kB (close to 249MB)
• max_wal_size: 1GB
• min_wal_size: 512MB
• shared_buffers: 510920kB (close to 499MB)
• max_locks_per_transaction 1000
• wal_buffers: 15320kB (close to 15MB)
• work_mem: 2554kB
• effective_io_concurrency: 200
• dynamic_shared_memory_type: posix
On this instance we installed a postgres extension called timescaledb to gain performance on other tables. Some of these parameters were set using recommendations from that extension.

Instance managed by RDS (2 vCPUs, 2 GiB RAM, 250GB disk, 750 de IOPS):
• effective_cache_size: 1887792kB (close to 1844MB)
• maintenance_work_mem: 64MB
• max_wal_size: 2GB
• min_wal_size: 192MB
• shared_buffers: 943896kB (close to 922MB)
• max_locks_per_transaction 64

Operating system and version by runing "uname -a":
• VM on GCP:
Linux {{{my instance name}}} 4.19.0-14-cloud-amd64 #1 SMP Debian 4.19.171-2 (2021-01-30) x86_64 GNU/Linux
• Managed by AWS RDS: Aparently Red Hay as shown using SELECT version();

Program used to connect to PostgreSQL: Python psycopg2.connect() to create the connection and pandas read_sql_query() to query using that connection.

Thanks in advance
--------------4D75A144FFF51D2F20F412A7--