First, let’s try gocmdpev.
Install go
[ec2-user@bastin ~]$ sudo yum -y install go
Loaded plugins: langpacks, priorities, update-motd
amzn2-core | 3.7 kB 00:00:00
228 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
~omitted~
Installed:
golang.x86_64 0:1.15.14-1.amzn2.0.1
Dependency Installed:
apr.x86_64 0:1.6.3-5.amzn2.0.2 apr-util.x86_64 0:1.6.1-5.amzn2.0.2 apr-util-bdb.x86_64 0:1.6.1-5.amzn2.0.2 golang-bin.x86_64 0:1.15.14-1.amzn2.0.1 golang-src.noarch 0:1.15.14-1.amzn2.0.1
mercurial.x86_64 0:2.6.2-10.amzn2 neon.x86_64 0:0.30.0-3.amzn2.0.2 pakchois.x86_64 0:0.4-10.amzn2.0.2 subversion.x86_64 0:1.7.14-16.amzn2.0.1 subversion-libs.x86_64 0:1.7.14-16.amzn2.0.1
Complete!
[ec2-user@bastin ~]$
[ec2-user@bastin ~]$ go version
go version go1.15.14 linux/amd64
[ec2-user@bastin ~]$ go get -u github.com/simon-engledew/gocmdpev
[ec2-user@bastin ~]$ echo $?
0
[ec2-user@bastin ~]$ ./go/bin/gocmdpev --version
1.0.0
Generating test data for visualization
pgbench -i -s 100 -U postgres -h xxxx.cluster-xxxx.ap-northeast-1.rds.amazonaws.com pgbench
Test SQL
EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON) SELECT t1.aid,t1.bid,t1.abalance,t2.bbalance FROM pgbench_accounts t1, pgbench_branches t2 where t1.bid=t2.bid ORDER BY t1.abalance DESC;
This SQL involves sorting and joins, which may be problematic.

Generate an execution plan for passing to gocmdpev with FORMAT specification.
vi explain.sql
Write the following SQL to explain.sql. Specify ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON as EXPLAIN options.
EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON) SELECT t1.aid,t1.bid,t1.abalance,t2.bbalance FROM pgbench_accounts t1, pgbench_branches t2 where t1.bid=t2.bid ORDER BY t1.abalance DESC;
Execute the SQL and output the execution plan to analyze.json.
psql -h auroraserverlessv1.cluster-cm678nkt5thr.ap-northeast-1.rds.amazonaws.com -U postgres -d pgbench -qAt -f explain.sql > analyze.json
Pass the output analyze.json to gocmdpev.
cat analyze.json | gocmdpev
The output below shows where time is being spent with color coding, making analysis easier.

[ec2-user@bastin ~]$ cat analyze.json | gocmdpev
โ Total Cost: 1,790,852.84
โ Planning Time: 53.45 ms
โ Execution Time: 7.92 s
โฌ
โ
โโโ Gather Merge costliest largest
โ
โ โ Duration: 2.03 s (26%)
โ โ Cost: 962,873.54 (54%)
โ โ Rows: 10,000,000
โ rows Underestimated by 1.20x
โโบ t1.aid + t1.bid + t1.abalance + t2.bbalance
โ
โโโ Sort slowest
โ Sorts a record set based on the specified sort key.
โ โ Duration: 6.60 s (83%)
โ โ Cost: 610,973.3400000001 (34%)
โ โ Rows: 3,333,333
โ rows Overestimated by 1.25x
โโบ t1.aid + t1.bid + t1.abalance + t2.bbalance
โ
โโโ Hash Join
โ Joins to record sets by hashing one of them (using
โ a Hash Scan).
โ โ Duration: 4.88 s (62%)
โ โ Cost: 11,402.289999999979 (1%)
โ โ Rows: 3,333,333
โ Inner join
โ on (t1.bid = t2.bid)
โ rows Overestimated by 1.25x
โโบ t1.aid + t1.bid + t1.abalance + t2.bbalance
โ
โโโ Seq Scan
โ โ Finds relevant records by sequentially
โ โ scanning the input record set. When reading
โ โ from a table, Seq Scans (unlike Index Scans)
โ โ perform a single read operation (only the
โ โ table is read).
โ โ โ Duration: 5.12 s (65%)
โ โ โ Cost: 205,601.67 (11%)
โ โ โ Rows: 3,333,333
โ โ on public.pgbench_accounts
โ โ rows Overestimated by 1.25x
โ โกโบ t1.aid + t1.bid + t1.abalance
โ
โโโ Hash
โ Generates a hash table from the records in the
โ input recordset. Hash is used by Hash Join.
โ โ Duration: <1 ms (0%)
โ โ Cost: 0 (0%)
โ โ Rows: 100
โโบ t2.bbalance + t2.bid
โ
โโโ Seq Scan
โ Finds relevant records by sequentially
โ scanning the input record set. When reading
โ from a table, Seq Scans (unlike Index Scans)
โ perform a single read operation (only the
โ table is read).
โ โ Duration: <1 ms (0%)
โ โ Cost: 2 (0%)
โ โ Rows: 100
โ on public.pgbench_branches
โกโบ t2.bbalance + t2.bid
There is also a visualization tool called pev. It may be more intuitive and easier to read. You can choose between CLI-based gocmdpev and GUI-based pev. Like gocmdpev, pev can visualize execution plans by loading ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON output.
As stated below, plans are processed locally, but it may be wise to be cautious:
DISCLAIMER: Pev stores your plans locally (localStorage) and will not send them anywhere.


Make PostgreSQL EXPLAIN easier to read with pev and gocmdpev | gocmdpev https://wonderwall.hatenablog.com/entry/2017/09/13/220000