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 1mYC4K-0001Yn-Tv for pgsql-performance@arkaria.postgresql.org; Wed, 06 Oct 2021 18:55:09 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1mYC4J-0004kg-IF for pgsql-performance@arkaria.postgresql.org; Wed, 06 Oct 2021 18:55:07 +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 1mYC4J-0004jn-2z for pgsql-performance@lists.postgresql.org; Wed, 06 Oct 2021 18:55:07 +0000 Received: from mail-qt1-x82e.google.com ([2607:f8b0:4864:20::82e]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1mYC4F-0008Si-63 for pgsql-performance@lists.postgresql.org; Wed, 06 Oct 2021 18:55:06 +0000 Received: by mail-qt1-x82e.google.com with SMTP id b16so3682505qtt.7 for ; Wed, 06 Oct 2021 11:55:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:subject:content-language:to :references:from:in-reply-to; bh=dUgLvurqgwF6o8SA/F5JASDugKJNVUyeCfPRhmuYyuY=; b=oCuSsXROMZu4mwYisFkxo4/jb/7cmFMfAirlkSY9pJK4HGBInw0Yr/num940171a1v +AL0KUJN8XD1O6HLry/gT6hp6zvU6gJRlUwaZhN91ywmGK7aTjLNRVJpIfw6DlXK2ODI WWawFMTLwMMi09lwxx2oEu8b84aSA875OqfMU8Nx1Si4c9ZtaQMQDH+FUm0XCl4cOeyU sny7x2wJmX3XAdnav0vcSCj3FQowBuxkJ5TuGcFxZnqZYgWVFSg57enEU4GA7kVYm7BL Ez+WAHJtML8f1uq5k3ge1xPfHHmd0eWvh7y6y8zCchQkRI+nf+M/1TpbL4Srkaeih2QS 1HYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:references:from:in-reply-to; bh=dUgLvurqgwF6o8SA/F5JASDugKJNVUyeCfPRhmuYyuY=; b=rlKXYzLNRNsKEaICCrPi6QDcWNz2GWMhCCGOH05B6QSCa7bejh4QT97DJ6j5sYCkS1 1s/wyTemCIy3eVaCtWi3OeYxrEtzfBX5CYKp1K5lpSobdwDgNk0doXnTYpz9iXEpWuL1 2zbLdHiaH1AKUeCVX5uTHDrFMV55P63aOlvTK7QVjvKVbHSzu3/ZMgmBHtuimna5lfD0 n3nouRtw9m4ifX+eXLh6AhACKTUe4OsWqGn+czQojZwPGq69HR5Wfmk1lAHsdqBII3qp CEKxA6NdsttRIAvf9jQVvL+731jamcy2QW3Noo5vuW8N4KuEdWDz0YZcOiazJWqVMP/1 eCSA== X-Gm-Message-State: AOAM533LmupmYff82q78lo/zdA+wYXKE580+os4Rk6Bp0NAJE8ZnFuzl aUtsR6gXvdbUK09r8sWN3vr1/OQAP5p8JA== X-Google-Smtp-Source: ABdhPJzZ4sid1sIaylKbD1SLM9oBIxku/D4IUhMD2rB20KCRKt5B6wYKig87drzIwGXdBPitK5aM1g== X-Received: by 2002:ac8:4243:: with SMTP id r3mr423747qtm.187.1633546501208; Wed, 06 Oct 2021 11:55:01 -0700 (PDT) Received: from [192.168.2.100] (pool-72-79-19-93.nwrknj.east.verizon.net. [72.79.19.93]) by smtp.gmail.com with ESMTPSA id u20sm12260339qke.66.2021.10.06.11.55.00 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 06 Oct 2021 11:55:00 -0700 (PDT) Content-Type: multipart/alternative; boundary="------------gVVZsLkjC2yH5Vg8AtWyOlra" Message-ID: <5c336778-df1a-f440-8feb-31c5ffbc9188@gmail.com> Date: Wed, 6 Oct 2021 14:54:59 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.1.0 Subject: Re: Troubleshooting a long running delete statement Content-Language: en-US To: pgsql-performance@lists.postgresql.org References: From: Mladen Gogala In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------gVVZsLkjC2yH5Vg8AtWyOlra Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 10/6/21 14:00, Dirschel, Steve wrote: > Question: > How would one troubleshoot this issue in Postgres as to why the delete > was running so long?  My background is Oracle and there are various > statistics I may look at: > > * One could estimate the number of logical reads the delete should > do based on expected number of rows to delete, expected logical > reads against the table per row, expected logical reads against > each index per row. > * One could look in V$SQL and see how many logical reads the query > was actually doing. > * One could look at V$SESS_IO and see how many logical reads the > session was doing. > > In this case you would see the query was doing way more logical reads > that expected and then try and think of scenarios that would cause that. > Here is what I could see in Postgres: > > * When I did an explain on the delete I could see it was full > scanning the table. I did a full scan of the table interactively > in less than 1 second so the long runtime was not due to the full > tablescan. > * I could not find the query in pg_stat_statements to see how many > shared block reads/hits the query was doing to see if the numbers > were extremely high.  Based on documentation queries do not show > up in pg_stat_statements until after they complete. > * pg_stat_activity showed wait_event_type and wait_event were null > for the session every time I looked.  So the session was > continually using CPU. > > I started looking at table definitions (indexes, FK's, etc.) and > comparing to Oracle and noticed some indexes missing.  I then could > see the table being deleted from was a child table with a FK pointing > to a parent table.  Finally I was able to see that the parent table > was missing an index on the FK column so for every row being deleted > from the child it was full scanning the parent.  All makes sense after > the fact but I'm looking for a more methodical way to come to that > conclusion by looking at database statistics. > Are there other statistics in Postgres I may have looked at to > methodically come to the conclusion that the problem was the missing > index on the parent FK column? > Thanks > This e-mail is for the sole use of the intended recipient and contains > information that may be privileged and/or confidential. If you are not > an intended recipient, please notify the sender by return e-mail and > delete this e-mail and any attachments. Certain required legal entity > disclosures can be accessed on our website: > https://www.thomsonreuters.com/en/resources/disclosures.html Hi Steve, First, check whether you have any triggers on the table. The best way of doing it is to use information_schema.triggers. I have seen triggers introduce some "mysterious" functionality in Oracle as well. Second, check constraints. Is the table you're deleting from the parent table of a foreign key constraint(s)? If the constraints are defined with "ON DELETE CASCADE", you maybe deleting more than you think. If it is not defined with "ON DELETE CASCADE" or "ON DELETE SET NULL", you would get an error. If that passes the muster, then check the processes doing the most of IO using "iotop" or "atop". I like the latter. You can then check what the busy processes are doing using strace -e trace=file and, for good measure, 'perf top". Regards -- Mladen Gogala Database Consultant Tel: (347) 321-1217 https://dbwhisperer.wordpress.com --------------gVVZsLkjC2yH5Vg8AtWyOlra Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

On 10/6/21 14:00, Dirschel, Steve wrote:

Question:
 
How would one troubleshoot this issue in Postgres as to why the delete was running so long?  My background is Oracle and there are various statistics I may look at:
  • One could estimate the number of logical reads the delete should do based on expected number of rows to delete, expected logical reads against the table per row, expected logical reads against each index per row. 
  • One could look in V$SQL and see how many logical reads the query was actually doing.
  • One could look at V$SESS_IO and see how many logical reads the session was doing.
 
In this case you would see the query was doing way more logical reads that expected and then try and think of scenarios that would cause that.
 
Here is what I could see in Postgres:
  • When I did an explain on the delete I could see it was full scanning the table. I did a full scan of the table interactively in less than 1 second so the long runtime was not due to the full tablescan.
  • I could not find the query in pg_stat_statements to see how many shared block reads/hits the query was doing to see if the numbers were extremely high.  Based on documentation queries do not show up in pg_stat_statements until after they complete.
  • pg_stat_activity showed wait_event_type and wait_event were null for the session every time I looked.  So the session was continually using CPU.
 
I started looking at table definitions (indexes, FK's, etc.) and comparing to Oracle and noticed some indexes missing.  I then could see the table being deleted from was a child table with a FK pointing to a parent table.  Finally I was able to see that the parent table was missing an index on the FK column so for every row being deleted from the child it was full scanning the parent.  All makes sense after the fact but I'm looking for a more methodical way to come to that conclusion by looking at database statistics.
 
Are there other statistics in Postgres I may have looked at to methodically come to the conclusion that the problem was the missing index on the parent FK column?
 
Thanks
 
This e-mail is for the sole use of the intended recipient and contains information that may be privileged and/or confidential. If you are not an intended recipient, please notify the sender by return e-mail and delete this e-mail and any attachments. Certain required legal entity disclosures can be accessed on our website: https://www.thomsonreuters.com/en/resources/disclosures.html


Hi Steve,

First, check whether you have any triggers on the table. The best way of doing it is to use information_schema.triggers. I have seen triggers introduce some "mysterious" functionality in Oracle as well. Second, check constraints. Is the table you're deleting from the parent table of a foreign key constraint(s)? If the constraints are defined with "ON DELETE CASCADE", you maybe deleting more than you think. If it is not defined with "ON DELETE CASCADE" or "ON DELETE SET NULL", you would get an error. If that passes the muster, then check the processes doing the most of IO using "iotop" or "atop". I like the latter. You can then check what the busy processes are doing using strace -e trace=file and, for good measure, 'perf top".

Regards

-- 
Mladen Gogala
Database Consultant
Tel: (347) 321-1217
https://dbwhisperer.wordpress.com
--------------gVVZsLkjC2yH5Vg8AtWyOlra--