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 1p4FuD-00086P-Ty for pgsql-hackers@arkaria.postgresql.org; Sun, 11 Dec 2022 06:33:46 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1p4FuC-0005gd-Fi for pgsql-hackers@arkaria.postgresql.org; Sun, 11 Dec 2022 06:33:44 +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 1p4FuB-0005gU-Rl for pgsql-hackers@lists.postgresql.org; Sun, 11 Dec 2022 06:33:44 +0000 Received: from mail-il1-x12b.google.com ([2607:f8b0:4864:20::12b]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1p4Fu5-0006RQ-Ok for pgsql-hackers@lists.postgresql.org; Sun, 11 Dec 2022 06:33:42 +0000 Received: by mail-il1-x12b.google.com with SMTP id x12so1962486ilg.1 for ; Sat, 10 Dec 2022 22:33:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20210112.gappssmtp.com; s=20210112; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=99oUxjL/Rkd3AP13g8XGLYVMNmGkkSldTyuY9MsgGRM=; b=ejsD/is9+o9H/rQBBB6GS34l9KpjCM+RDVRAYiV46ix0nqFRgqbfkJAJMVY0SZv0ue eHQcgJkt/CwjnEDP5H1zKiOI0PWiaDEAqCWxQEuACyMgq45wtUqliCCder7JZEj7JpEE 4mEidbERFej2hsFVR+vYTNi6MrhWJYvf3j/Kn7ejuaR3Zrl9/sTIwW7LTu7bFFuPx895 cjlZD7u3QI9BoBD9PvW/sg9uTVjJbsvd5bPgIizj5gONQ3HQKQKVFBBvu79Zb7gvpIC3 B/DWLMZ8272x6DPxG6O+9LMveqjUG39F0IGb+pWZd+D7e/FY92tw6zlRfkgjHexx/cPn KdIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=99oUxjL/Rkd3AP13g8XGLYVMNmGkkSldTyuY9MsgGRM=; b=AtdrSKW2cfhyJwqe7D/sIbu6Npm+bXsyTLVYZjBRI6KRwhGXdFUN3BIzJY2SAE8ePE LdObntA9KJ/ksEZdF+xWsQcE1+gbHP4FqrR1LRZlQAn7cay+oQMRb5vNwtV/JGGis3bS 8+Sc4IVGnUEnYYFLdc0DW3AwXh7wHGlFe6XopHMCb4yOdB2wMoikQLtvt+micNimBLrm j9HRoXpzZhcjp0DGa97D9yc4Yn8ZNU4earlrZXCAkhKHXzDAzwQ6+J5rW0VyDsEANb3j mykM3r8SGIXFTuDFrvrKhu9UNY1x8Rj0Rnxw2Bksp3MtCYydGul3FBQQ5LgAbvCrTVjD k8wg== X-Gm-Message-State: ANoB5pm9Bd1UMEV2Xf5Ubk8w6a9PYR+QtabLs9Ht5M4Vo/D885ryboVV gGWnmaqdfzmDiSO0MVyITE1m6Q== X-Google-Smtp-Source: AA0mqf68kl7GumpkqtVjCJtTDCsJN7t4NG2yLXlFinE+IxlH4BsnvHaRTtDMemiuzD//oZ/CkQs/dQ== X-Received: by 2002:a92:d710:0:b0:302:759a:c50 with SMTP id m16-20020a92d710000000b00302759a0c50mr6022576iln.11.1670740416697; Sat, 10 Dec 2022 22:33:36 -0800 (PST) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id h2-20020a92c082000000b002f916f15625sm1979857ile.23.2022.12.10.22.33.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 Dec 2022 22:33:35 -0800 (PST) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 7015B800DAB; Sun, 11 Dec 2022 00:33:34 -0600 (CST) Date: Sun, 11 Dec 2022 00:33:34 -0600 From: Justin Pryzby To: Ilya Gladyshev Cc: pgsql-hackers@lists.postgresql.org Subject: Re: Progress report of CREATE INDEX for nested partitioned tables Message-ID: <20221211063334.GB27893@telsasoft.com> References: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Kj7319i9nmIyA2yE" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Kj7319i9nmIyA2yE Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Sat, Dec 10, 2022 at 12:18:32PM +0400, Ilya Gladyshev wrote: > Hi, > > I have noticed that progress reporting for CREATE INDEX of partitioned > tables seems to be working poorly for nested partitioned tables. In > particular, it overwrites total and done partitions count when it > recurses down to child partitioned tables and it only reports top-level > partitions. So it's not hard to see something like this during CREATE > INDEX now: > > postgres=# select partitions_total, partitions_done from > pg_stat_progress_create_index ; > partitions_total | partitions_done > ------------------+----------------- > 1 | 2 > (1 row) Yeah. I didn't verify, but it looks like this is a bug going to back to v12. As you said, when called recursively, DefineIndex() clobbers the number of completed partitions. Maybe DefineIndex() could flatten the list of partitions. But I don't think that can work easily with iteration rather than recursion. Could you check what I've written as a counter-proposal ? As long as we're changing partitions_done to include nested sub-partitions, it seems to me like we should exclude intermediate "catalog-only" partitioned indexes, and count only physical leaf partitions. Should it alo exclude any children with matching indexes, which will also be catalog-only changes? Probably not. The docs say: |When creating an index on a partitioned table, this column is set to the |total number of partitions on which the index is to be created. This |field is 0 during a REINDEX. > I changed current behaviour to report the total number of partitions in > the inheritance tree and fixed recursion in the attached patch. I used > a static variable to keep the counter to avoid ABI breakage of > DefineIndex, so that we could backpatch this to previous versions. I wrote a bunch of assertions for this, which seems to have uncovered an similar issue with COPY progress reporting, dating to 8a4f618e7. I'm not sure the assertions are okay. I imagine they may break other extensions, as with file_fdw. -- Justin --Kj7319i9nmIyA2yE Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-fix-progress-reporting-of-nested-partitioned-indexes.patch" From b8077babf9a101f9d1bf41dd1ad866d2ea38b603 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Sat, 10 Dec 2022 16:17:50 -0600 Subject: [PATCH] fix progress reporting of nested, partitioned indexes.. --- src/backend/commands/indexcmds.c | 51 +++++++++++-- src/backend/utils/activity/backend_progress.c | 72 +++++++++++++++++++ 2 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index b5b860c3abf..6caa1f94ed7 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -482,6 +482,26 @@ WaitForOlderSnapshots(TransactionId limitXmin, bool progress) } } +/* + * Count the number of direct and indirect leaf partitions, excluding foreign + * tables. + */ +static int +num_leaf_partitions(Oid relid) +{ + int nleaves = 0; + List *childs = find_all_inheritors(relid, NoLock, NULL); + ListCell *lc; + + foreach(lc, childs) + { + Oid partrelid = lfirst_oid(lc); + if (RELKIND_HAS_STORAGE(get_rel_relkind(partrelid))) + nleaves++; + } + + return nleaves; +} /* * DefineIndex @@ -1212,14 +1232,22 @@ DefineIndex(Oid relationId, partdesc = RelationGetPartitionDesc(rel, true); if ((!stmt->relation || stmt->relation->inh) && partdesc->nparts > 0) { - int nparts = partdesc->nparts; + int nparts = partdesc->nparts; /* only direct children */ + int nparts_done = 0; /* direct and indirect children */ Oid *part_oids = palloc_array(Oid, nparts); bool invalidate_parent = false; Relation parentIndex; TupleDesc parentDesc; - pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_TOTAL, - nparts); + if (!OidIsValid(parentIndexId)) + { + /* + * Report the number of leaf partitions (excluding foreign + * tables), not just direct children. + */ + pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_TOTAL, + num_leaf_partitions(relationId)); + } /* Make a local copy of partdesc->oids[], just for safety */ memcpy(part_oids, partdesc->oids, sizeof(Oid) * nparts); @@ -1431,8 +1459,21 @@ DefineIndex(Oid relationId, child_save_sec_context); } - pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_DONE, - i + 1); + if (!OidIsValid(parentIndexId)) + { + /* + * Report progress only when processing top-level indexes. + * When recursing, the called functions wouldn't know the + * current number of partitions which were processed. + * After recursing, increment by the number of children. + * This works also for physical/leaf partitions. + */ + nparts_done += num_leaf_partitions(childRelid); + + pgstat_progress_update_param(PROGRESS_CREATEIDX_PARTITIONS_DONE, + nparts_done); + } + free_attrmap(attmap); } diff --git a/src/backend/utils/activity/backend_progress.c b/src/backend/utils/activity/backend_progress.c index f29199725b7..1db1332ebe6 100644 --- a/src/backend/utils/activity/backend_progress.c +++ b/src/backend/utils/activity/backend_progress.c @@ -10,6 +10,7 @@ */ #include "postgres.h" +#include "commands/progress.h" #include "port/atomics.h" /* for memory barriers */ #include "utils/backend_progress.h" #include "utils/backend_status.h" @@ -37,6 +38,75 @@ pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid) PGSTAT_END_WRITE_ACTIVITY(beentry); } +static void +pgstat_progress_asserts(void) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + volatile int64 *a = beentry->st_progress_param; + + switch (beentry->st_progress_command) + { + case PROGRESS_COMMAND_VACUUM: + Assert(a[PROGRESS_VACUUM_HEAP_BLKS_SCANNED] == + a[PROGRESS_VACUUM_TOTAL_HEAP_BLKS]); + Assert(a[PROGRESS_VACUUM_HEAP_BLKS_VACUUMED] == + a[PROGRESS_VACUUM_TOTAL_HEAP_BLKS]); + Assert(a[PROGRESS_VACUUM_NUM_DEAD_TUPLES] <= + a[PROGRESS_VACUUM_MAX_DEAD_TUPLES]); + break; + + case PROGRESS_COMMAND_ANALYZE: + Assert(a[PROGRESS_ANALYZE_BLOCKS_DONE] == + a[PROGRESS_ANALYZE_BLOCKS_TOTAL]); + Assert(a[PROGRESS_ANALYZE_EXT_STATS_COMPUTED] <= + a[PROGRESS_ANALYZE_EXT_STATS_TOTAL]); + Assert(a[PROGRESS_ANALYZE_CHILD_TABLES_DONE] == + a[PROGRESS_ANALYZE_CHILD_TABLES_TOTAL]); + break; + + case PROGRESS_COMMAND_CLUSTER: + Assert(a[PROGRESS_CLUSTER_HEAP_BLKS_SCANNED] == + a[PROGRESS_CLUSTER_TOTAL_HEAP_BLKS]); + break; + + case PROGRESS_COMMAND_CREATE_INDEX: + Assert(a[PROGRESS_CREATEIDX_TUPLES_DONE] <= + a[PROGRESS_CREATEIDX_TUPLES_TOTAL]); + Assert(a[PROGRESS_CREATEIDX_PARTITIONS_DONE] == + a[PROGRESS_CREATEIDX_PARTITIONS_TOTAL]); + break; + + case PROGRESS_COMMAND_BASEBACKUP: + /* progress is optional */ + if (a[PROGRESS_BASEBACKUP_BACKUP_TOTAL] >= 0) + { + Assert(a[PROGRESS_BASEBACKUP_BACKUP_STREAMED] == + a[PROGRESS_BASEBACKUP_BACKUP_TOTAL]); + Assert(a[PROGRESS_BASEBACKUP_TBLSPC_STREAMED] == + a[PROGRESS_BASEBACKUP_TBLSPC_TOTAL]); + } + break; + + case PROGRESS_COMMAND_COPY: +#if 0 +// This currently fails file_fdw tests, since pgstat_prorgress evidently fails +// to support simultaneous copy commands, as happens during JOIN. + /* bytes progress is not available in all cases */ + if (a[PROGRESS_COPY_BYTES_TOTAL] > 0) + // Assert(a[PROGRESS_COPY_BYTES_PROCESSED] <= a[PROGRESS_COPY_BYTES_TOTAL]); + if (a[PROGRESS_COPY_BYTES_PROCESSED] > a[PROGRESS_COPY_BYTES_TOTAL]) + elog(WARNING, "PROGRESS_COPY_BYTES_PROCESSED %ld %ld", + a[PROGRESS_COPY_BYTES_PROCESSED], + a[PROGRESS_COPY_BYTES_TOTAL]); + + break; +#endif + + case PROGRESS_COMMAND_INVALID: + break; /* Do nothing */ + } +} + /*----------- * pgstat_progress_update_param() - * @@ -105,6 +175,8 @@ pgstat_progress_end_command(void) if (beentry->st_progress_command == PROGRESS_COMMAND_INVALID) return; + pgstat_progress_asserts(); + PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); beentry->st_progress_command = PROGRESS_COMMAND_INVALID; beentry->st_progress_command_target = InvalidOid; -- 2.25.1 --Kj7319i9nmIyA2yE--