DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • SQL Server to Postgres Database Migration
  • How to Build a Full-Stack App With Next.js, Prisma, Postgres, and Fastify
  • How to Store Text in PostgreSQL: Tips, Tricks, and Traps
  • PostgreSQL Rewrite Rules

Trending

  • Beyond ChatGPT, AI Reasoning 2.0: Engineering AI Models With Human-Like Reasoning
  • How to Practice TDD With Kotlin
  • DGS GraphQL and Spring Boot
  • How to Configure and Customize the Go SDK for Azure Cosmos DB
  1. DZone
  2. Data Engineering
  3. Databases
  4. Useful PostgreSQL Commands/Queries

Useful PostgreSQL Commands/Queries

In this article, we will briefly discuss some queries and their uses, specifically in the case of both monitoring and debugging PostgreSQL-related issues.

By 
Sahil Aggarwal user avatar
Sahil Aggarwal
·
Apr. 27, 21 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
7.9K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

There are many types of queries and of course, all are important, but when it comes to monitoring and debugging, we are generally in a hurry and do not remember what to query to check for a specific problem/issue. In this blog, we will briefly discuss some queries and their uses, specifically in the case of monitoring and debugging PostgreSQL-related issues.

In the case of monitoring and debugging, we generally have the following categorical issues: size-related and performance-related. Sometimes these issues are interlinked.

Size-Related Issues

Here are some basic Postgres commands/queries which will be very helpful in monitoring or debugging size-related issues:

  • Checking the Size of the Database: There are many times where we need to check which database is the culprit of an issue i.e… which database is consuming major space . Following is a query to check the size of a database in decreasing order according to size consumed.
SQL
 




x


 
1
SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database ORDER BY pg_database_size(pg_database.datname) desc;



  • After that, we may need to find which table/index is consuming the most space; for this, we have the following query:
SQL
 




xxxxxxxxxx
1


 
1
SELECT
2
  nspname || '.' || relname AS "relation", pg_size_pretty(pg_relation_size(C.oid)) AS "size"
3
FROM pg_class C
4
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
5
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
6
ORDER BY pg_relation_size(C.oid) DESC
7
LIMIT 20;



There are many times where there are no records in the table, but due to dead tuples, the size of a table/index may increase. To check which table has the highest dead tuples, use the following query:

SQL
 




xxxxxxxxxx
1


 
1
SELECT schemaname,relname,n_live_tup,n_dead_tup,last_vacuum,last_autovacuum FROM pg_stat_user_tables ORDER BY n_dead_tup DESC limit 10;



Sample Output:

SQL
 




xxxxxxxxxx
1


 
1
schemaname | relname | n_live_tup | n_dead_tup | last_vacuum | last_autovacuum
2

          
3
— — — — — — + — — — — — — — — — — — — — — — — — — — — — — — — — + — — — — — — + — — — — — — + — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — — —
4

          
5
public | campaign_session_denormalized_data | 1123219 | 114268349 | 2021–01–10 18:27:34.050087+05:30 | 2021–01–19 14:08:58.062574+05:30



From the above output, we can also determine if the auto vacuum is running properly or not i.e... When the last auto vacuum ran on any particular table whose dead tuples are high.

Over time, due to MVCC, your table will grow in size (called table bloat)—this is why regular VACUUM is needed. This query will show you a list of tables and indexes with the most bloats. The value represents the number of “wasted bytes," or the difference between what is actually used by the table and index, and what we compute that it should be.

The way it works is it estimates the optimized size of the table/index by a calculation from each row sizes times total rows and compares that against the actual table size. Do note that this is an estimate, not an actual figure.

SQL
 




xxxxxxxxxx
1
48


 
1
with foo as (
2
  SELECT
3
    schemaname, tablename, hdr, ma, bs,
4
    SUM((1-null_frac)*avg_width) AS datawidth,
5
    MAX(null_frac) AS maxfracsum,
6
    hdr+(
7
      SELECT 1+COUNT(*)/8
8
      FROM pg_stats s2
9
      WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename
10
    ) AS nullhdr
11
  FROM pg_stats s, (
12
    SELECT
13
      (SELECT current_setting('block_size')::NUMERIC) AS bs,
14
      CASE WHEN SUBSTRING(v,12,3) IN ('8.0','8.1','8.2') THEN 27 ELSE 23 END AS hdr,
15
      CASE WHEN v ~ 'mingw32' THEN 8 ELSE 4 END AS ma
16
    FROM (SELECT version() AS v) AS foo
17
  ) AS constants
18
  GROUP BY 1,2,3,4,5  
19
), rs as (
20
  SELECT
21
    ma,bs,schemaname,tablename,
22
    (datawidth+(hdr+ma-(CASE WHEN hdr%ma=0 THEN ma ELSE hdr%ma END)))::NUMERIC AS datahdr,
23
    (maxfracsum*(nullhdr+ma-(CASE WHEN nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
24
  FROM foo  
25
), sml as (
26
  SELECT
27
    schemaname, tablename, cc.reltuples, cc.relpages, bs,
28
    CEIL((cc.reltuples*((datahdr+ma-
29
      (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::FLOAT)) AS otta,
30
    COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
31
    COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::FLOAT)),0) AS iotta -- very rough approximation, assumes all cols
32
  FROM rs
33
  JOIN pg_class cc ON cc.relname = rs.tablename
34
  JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = rs.schemaname AND nn.nspname <> 'information_schema'
35
  LEFT JOIN pg_index i ON indrelid = cc.oid
36
  LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
37
)
38

          
39

          
40
SELECT
41
  current_database(), schemaname, tablename, /*reltuples::bigint, relpages::bigint, otta,*/
42
  ROUND((CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages::FLOAT/otta END)::NUMERIC,1) AS tbloat,
43
  CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::BIGINT END AS wastedbytes,
44
  iname, /*ituples::bigint, ipages::bigint, iotta,*/
45
  ROUND((CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages::FLOAT/iotta END)::NUMERIC,1) AS ibloat,
46
  CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes
47
FROM sml
48
ORDER BY wastedbytes DESC


Query extracted but rewritten from checkpostgres

Sample Output

SQL
 




xxxxxxxxxx
1
23


 
1
current_database | schemaname | tablename | tbloat | wastedbytes | iname | ibloat | wastedibytes
2

          
3
— — — — — — — — — + — — — — — — + — — — — — — — — — — — — — — — — -+ — — — — + — — — — — — -+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+ — — — — + — — — — — — —
4

          
5
dashboard | public | job_logs | 1.1 | 4139507712 | job_logs_pkey | 0.2 | 0
6

          
7
dashboard | public | job_logs | 1.1 | 4139507712 | index_job_logs_on_job_id_and_created_at | 0.4 | 0
8

          
9
dashboard | public | events | 1.1 | 3571736576 | events_pkey | 0.1 | 0
10

          
11
dashboard | public | events | 1.1 | 3571736576 | index_events_on_tenant_id | 0.1 | 0
12

          
13
dashboard | public | events | 1.1 | 3571736576 | index_events_on_event_type | 0.2 | 0
14

          
15
dashboard | public | jobs | 1.1 | 2013282304 | index_jobs_on_status | 0.0 | 0
16

          
17
dashboard | public | jobs | 1.1 | 2013282304 | index_jobs_on_tag | 0.3 | 0
18

          
19
dashboard | public | jobs | 1.1 | 2013282304 | index_jobs_on_tenant_id | 0.2 | 0
20

          
21
dashboard | public | jobs | 1.1 | 2013282304 | index_jobs_on_created_at | 0.2 | 0
22

          
23
dashboard | public | jobs | 1.1 | 2013282304 | index_jobs_on_created_at_queued_or_running | 0.0 | 21086208



You should be looking at:

  • tbloat: Table bloat, the ratio between what it currently is, and what it can be optimized to.
  • wastedbytes: The number of bytes wasted.
  • ibloat & wastedibytes: The same as above, but for indexes.

When you see a table with high bloats, then consider running VACUUM ANALYZE on it.

Performance Related issues

For performance-related monitoring, we need to run the following queries, though it may be too much in a day-to-day scenario.

  • Get Running Queries (And Lock statuses) in PostgreSQL
SQL
 




xxxxxxxxxx
1


 
1
SELECT S.pid, age(clock_timestamp(), query_start),usename,query,L.mode,L.locktype,L.granted,s.datname FROM pg_stat_activity S inner join pg_locks L on S.pid = L.pid order by L.granted, L.pid DESC;



The above query may help if some particular query is running for hours and has taken some lock, due to other queries getting stuck on lock. It also shows the database name on which query is running. We can also determine if some connection is open and no query is running so there may be some session leak in your database (for more for about session leak read the following article)

  • To kill a particular query that is causing the issue, use this query:
SQL
 




xxxxxxxxxx
1


 
1
SELECT pg_cancel_backend(pid);



This will send a SIGINT to the current process.

I hope this article helps all of you with at least some of your time spent debugging. Please comment and follow me if you have any questions or want to discuss!

Database PostgreSQL sql

Published at DZone with permission of Sahil Aggarwal. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • SQL Server to Postgres Database Migration
  • How to Build a Full-Stack App With Next.js, Prisma, Postgres, and Fastify
  • How to Store Text in PostgreSQL: Tips, Tricks, and Traps
  • PostgreSQL Rewrite Rules

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!