postgresqlsql-tuningdatabase-tuningquery-tuningdatabase-tuning-advisor

Need suggestion for POSTGRES Tuning


I am in a need to run the few complicated queries frequently on my database, one of my queries is taking around 57 sec to execute, I am trying a way to tune my Postgres database, so, I can cut the execution time to half or more than that.

I have created indexes and adjusted a few parameters on the table, but it didn't help me.

I am using the Postgres version 9.6, and below are the parameters that I have used to tune the database.

  1. max_connections = 1500
  2. shared_buffers =8GB
  3. effective_cache_size = 8GB
  4. maintenance_work_mem = 2GB
  5. checkpoint_completion_target = 0.7
  6. wal_buffers = 16MB
  7. default_statistics_target = 100
  8. random_page_cost = 1.1
  9. effective_io_concurrency = 200
  10. work_mem = 910kB
  11. min_wal_size = 1GB
  12. max_wal_size = 4GB
  13. max_worker_processes = 48
  14. max_parallel_workers_per_gather = 24

The query is below

Explain Analyze SELECT a. SD_ID, a.SIP_PART, a.plan_notes, a.STEP_NO, a.PRODUCT_TYPE, a.P_ID,
TO_CHAR(MIN(a.SIPD_DATE), 'YYYY/MM/DD HH24:MI:SS'), SUM(CASE WHEN a.STATUS < 30 THEN a.THEO_SECONDS ELSE 0 END ), MAX(a.TRAIL_SECONDS), x. SD_ID, x.SIP_PART,
x.plan_notes, x.STEP_NO, x.PRODUCT_TYPE, x.P_ID,  TO_CHAR(MIN(x.SIPD_DATE), 'YYYY/MM/DD HH24:MI:SS'),
 SUM(x.THEO_SECONDS), SUM(CASE WHEN x.STATUS >= 30 THEN x.THEO_SECONDS ELSE 0 END ), MAX(x.TRAIL_SECONDS),
 MIN(a.PSEQ - x.PSEQ), CASE WHEN x. SD_ID <> a. SD_ID THEN MIN(x.BSEQ - a.BSEQ) ELSE 0 END, MIN(x.PSEQ), '', 0, 0, COUNT(1),
 SUM(CASE WHEN x.STATUS >= 30 THEN 1 ELSE 0 END ) , CASE WHEN MIN(x.BSEQ) > 0 AND MIN(a.BSEQ) > 0 AND MIN(x.BSEQ) <> MIN(a.BSEQ) AND MIN(x.POS) = MIN(a.POS) THEN MIN(x.STEP - a.STEP) ELSE 0 END
 FROM MYTESTABLE a, MYTESTABLE x
 WHERE a.SIPD_DATE >=  TO_TIMESTAMP('2020/07/20 00:00:00','YYYY/MM/DD HH24:MI:SS')
 AND a.SIPD_DATE <=  TO_TIMESTAMP('2020/07/20 23:59:59','YYYY/MM/DD HH24:MI:SS')  AND  a.HISTORY = 0 AND a.PSEQ > 0  AND x.HISTORY = 0 AND x.PSEQ > 0
 AND a.ORDER_NO = x.ORDER_NO  AND a.ITEM_NO = x.ITEM_NO  AND a.QTY = x.QTY  AND (       (a. SD_ID > 0 AND x. SD_ID > 0 AND a. SD_ID <> x. SD_ID
 AND ((a.BSEQ = 1 AND x.BSEQ > 1) OR (a.BSEQ > 1 AND x.BSEQ = 1)))
 OR       (a. SD_ID = x. SD_ID AND ((a.BSEQ = 1 AND x.BSEQ > 1) OR (a.BSEQ > 1 AND x.BSEQ = 1)))
 OR       (a. SD_ID = x. SD_ID AND a.BSEQ = x.BSEQ AND         ((a.PRODUCT_TYPE IS NULL AND x.PRODUCT_TYPE IS NULL)
 OR (a.PRODUCT_TYPE IS NOT NULL AND a.PRODUCT_TYPE = x.PRODUCT_TYPE AND a.P_ID = x.P_ID))
 AND         (a.plan_notes <> a.plan_notes OR a.STEP_NO <> x.STEP_NO) AND         a.PSEQ <> x.PSEQ)
 OR       (a. SD_ID = x. SD_ID AND a.BSEQ > 1 AND x.BSEQ > 1 AND a.BSEQ <> x.BSEQ AND        a.PRODUCT_TYPE = 1 AND x.PRODUCT_TYPE = 1
 AND a.P_ID <> x.P_ID AND a.POS = x.POS AND       ((a.STEP = 0 AND x.STEP > 0) OR (x.STEP = 0 AND a.STEP > 0))))
 GROUP BY a. SD_ID, a.SIP_PART,  a.plan_notes, a.STEP_NO, a.PRODUCT_TYPE, a.P_ID,  DATE_TRUNC('day', a.SIPD_DATE) ,
 x. SD_ID, x.SIP_PART,  x.plan_notes, x.STEP_NO, x.PRODUCT_TYPE, x.P_ID,  DATE_TRUNC('day', x.SIPD_DATE)  ORDER BY a. SD_ID,
 a.SIP_PART,  a.plan_notes, a.STEP_NO, a.PRODUCT_TYPE, a.P_ID,  DATE_TRUNC('day', a.SIPD_DATE) , x. SD_ID, x.SIP_PART,  MIN(x.PSEQ);

Below is the query plan

                                                                     QUERY PLAN


 Sort  (cost=5426751.71..5436426.08 rows=3869747 width=482) (actual time=57121.003..57139.244 rows=105225 loops=1)
   Sort Key: a. SD_ID, a.SIP_part, a.plan_notes, a.step_no, a.PRODUCT_TYPE, a.P_ID, (date_trunc('day'::text, a.SIPd_date)), x. SD_ID, x.SIP_part, (min(x.PSEQ))
   Sort Method: external sort  Disk: 19848kB
   ->  GroupAggregate  (cost=1982498.13..2524262.71 rows=3869747 width=482) (actual time=34888.529..56516.255 rows=105225 loops=1)
         Group Key: a. SD_ID, a.SIP_part, a.plan_notes, a.step_no, a.PRODUCT_TYPE, a.P_ID, (date_trunc('day'::text, a.SIPd_date)), x. SD_ID, x.SIP_part, x.plan_notes, x.step_no, x.PRODUCT_TYPE, x.P_ID, (dat
e_trunc('day'::text, x.SIPd_date))
         ->  Sort  (cost=1982498.13..1992172.50 rows=3869747 width=146) (actual time=34888.391..46834.281 rows=3195855 loops=1)
               Sort Key: a. SD_ID, a.SIP_part, a.plan_notes, a.step_no, a.PRODUCT_TYPE, a.P_ID, (date_trunc('day'::text, a.SIPd_date)), x. SD_ID, x.SIP_part, x.plan_notes, x.step_no, x.PRODUCT_TYPE, x.P_ID,
 (date_trunc('day'::text, x.SIPd_date))
               Sort Method: external merge  Disk: 519008kB
               ->  Gather  (cost=1000.56..877326.14 rows=3869747 width=146) (actual time=10.146..1648.706 rows=3195855 loops=1)
                     Workers Planned: 6
                     Workers Launched: 6
                     ->  Nested Loop  (cost=0.56..473227.49 rows=644958 width=146) (actual time=10.876..5330.931 rows=456551 loops=7)
                           ->  Parallel Seq Scan on MYTESTABLE a  (cost=0.00..278565.05 rows=167365 width=82) (actual time=10.771..975.060 rows=79290 loops=7)
                                 Filter: ((PSEQ > '0'::numeric) AND (history = '0'::numeric) AND (SIPd_date >= to_timestamp('2020/07/20 00:00:00'::text, 'YYYY/MM/DD HH24:MI:SS'::text)) AND (SIPd_date <= to_timestamp('2020/0
7/20 23:59:59'::text, 'YYYY/MM/DD HH24:MI:SS'::text)))
                                 Rows Removed by Filter: 386673
                           ->  Index Scan using idx_a1 on MYTESTABLE x  (cost=0.56..1.13 rows=1 width=82) (actual time=0.020..0.049 rows=6 loops=555028)
                                 Index Cond: ((order_no = a.order_no) AND (item_no = a.item_no) AND (QTY = a.QTY) AND (history = '0'::numeric) AND (PSEQ > '0'::numeric))
                                 Filter: (((a. SD_ID > '0'::numeric) AND ( SD_ID > '0'::numeric) AND (a. SD_ID <>  SD_ID) AND (((a.BSEQ = '1'::numeric) AND (BSEQ > '1'::numeric)) OR ((a.BSEQ > '1'::nume
ric) AND (BSEQ = '1'::numeric)))) OR ((a. SD_ID =  SD_ID) AND (((a.BSEQ = '1'::numeric) AND (BSEQ > '1'::numeric)) OR ((a.BSEQ > '1'::numeric) AND (BSEQ = '1'::numeric)))) OR ((a. SD_ID = SIP_
id) AND (a.BSEQ = BSEQ) AND (((a.PRODUCT_TYPE IS NULL) AND (PRODUCT_TYPE IS NULL)) OR ((a.PRODUCT_TYPE IS NOT NULL) AND (a.PRODUCT_TYPE = PRODUCT_TYPE) AND (a.P_ID = P_ID))) AND ((a.plan_notes <> a.plan_notes) OR (a.step_no <> step_n
o)) AND (a.PSEQ <> PSEQ)) OR ((a. SD_ID =  SD_ID) AND (a.BSEQ > '1'::numeric) AND (BSEQ > '1'::numeric) AND (a.BSEQ <> BSEQ) AND (a.PRODUCT_TYPE = '1'::numeric) AND (PRODUCT_TYPE = '1'::numeric) AND (a.mat_i
d <> P_ID) AND (a.POS = POS) AND (((a.STEP = '0'::numeric) AND (STEP > '0'::numeric)) OR ((STEP = '0'::numeric) AND (a.STEP > '0'::numeric)))))
                                 Rows Removed by Filter: 3
 Planning time: 9.241 ms
 Execution time: 57280.673 ms

Solution

  • It got fixed after updating to postgres10, the suggestion of jjanes worked