Thread
Commits
-
Add memory/disk usage for more executor nodes.
- 40708acd65c1 18.0 landed
-
Optimize tuplestore usage for WITH RECURSIVE CTEs
- 5d56d07ca343 18.0 landed
-
Add memory/disk usage for Window aggregate nodes in EXPLAIN.
- 95d6e9af07d2 18.0 landed
-
Optimize WindowAgg's use of tuplestores
- 908a968612f9 18.0 cited
-
Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-07-06T11:22:54Z
1eff8279d4 added memory/disk usage for materialize nodes in EXPLAIN ANALYZE. In the commit message: > There are a few other executor node types that use tuplestores, so we > could also consider adding these details to the EXPLAIN ANALYZE for > those nodes too. So I wanted to Add memory/disk usage for WindowAgg. Patch attached. Since WindowAgg node could create multiple tuplestore for each Window partition, we need to track each tuplestore storage usage so that the maximum storage usage is determined. For this purpose I added new fields to the WindowAggState. -- Tatsuo Ishii SRA OSS LLC English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-07-08T22:30:04Z
On Sat, 6 Jul 2024 at 23:23, Tatsuo Ishii <ishii@postgresql.org> wrote: > So I wanted to Add memory/disk usage for WindowAgg. Patch attached. Thanks for working on that. > Since WindowAgg node could create multiple tuplestore for each Window > partition, we need to track each tuplestore storage usage so that the > maximum storage usage is determined. For this purpose I added new > fields to the WindowAggState. I'd recently been looking at the code that recreates the tuplestore for each partition and thought we could do a bit better. In [1], I proposed a patch to make this better. If you based your patch on [1], maybe a better way of doing this is having tuplestore.c track the maximum space used on disk in an extra field which is updated with tuplestore_clear(). It's probably ok to update a new field called maxDiskSpace in tuplestore_clear() if state->status != TSS_INMEM. If the tuplestore went to disk then an extra call to BufFileSize() isn't going to be noticeable, even in cases where we only just went over work_mem. You could then adjust tuplestore_space_used() to look at maxDiskSpace and return that value if it's larger than BufFileSize(state->myfile) and state->maxSpace. You could check if maxDiskSpace == 0 to determine if the tuplestore has ever gone to disk. tuplestore_storage_type_name() would also need to check maxDiskSpace and return "Disk" if that's non-zero. David [1] https://www.postgresql.org/message-id/CAHoyFK9n-QCXKTUWT_xxtXninSMEv+gbJN66-y6prM3f4WkEHw@mail.gmail.com
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-07-09T02:44:12Z
> On Sat, 6 Jul 2024 at 23:23, Tatsuo Ishii <ishii@postgresql.org> wrote: >> So I wanted to Add memory/disk usage for WindowAgg. Patch attached. > > Thanks for working on that. Thank you for the infrastructure you created in tuplestore.c and explain.c. BTW, it seems these executor nodes (other than Materialize and Window Aggregate node) use tuplestore for their own purpose. CTE Scan Recursive Union Table Function Scan I have already implemented that for CTE Scan. Do you think other two nodes are worth to add the information? I think for consistency sake, it will better to add the info Recursive Union and Table Function Scan. >> Since WindowAgg node could create multiple tuplestore for each Window >> partition, we need to track each tuplestore storage usage so that the >> maximum storage usage is determined. For this purpose I added new >> fields to the WindowAggState. > > I'd recently been looking at the code that recreates the tuplestore > for each partition and thought we could do a bit better. In [1], I > proposed a patch to make this better. > > If you based your patch on [1], maybe a better way of doing this is > having tuplestore.c track the maximum space used on disk in an extra > field which is updated with tuplestore_clear(). It's probably ok to > update a new field called maxDiskSpace in tuplestore_clear() if > state->status != TSS_INMEM. If the tuplestore went to disk then an > extra call to BufFileSize() isn't going to be noticeable, even in > cases where we only just went over work_mem. You could then adjust > tuplestore_space_used() to look at maxDiskSpace and return that value > if it's larger than BufFileSize(state->myfile) and state->maxSpace. > You could check if maxDiskSpace == 0 to determine if the tuplestore > has ever gone to disk. tuplestore_storage_type_name() would also need > to check maxDiskSpace and return "Disk" if that's non-zero. Thank you for the suggestion. Yes, I noticed [1] and once it is committed, I will start to study tuplestore.c in this direction. Best reagards, -- Tatsuo Ishii SRA OSS LLC English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-07-09T02:49:41Z
On Tue, 9 Jul 2024 at 14:44, Tatsuo Ishii <ishii@postgresql.org> wrote: > BTW, it seems these executor nodes (other than Materialize and Window > Aggregate node) use tuplestore for their own purpose. > > CTE Scan > Recursive Union > Table Function Scan > > I have already implemented that for CTE Scan. Do you think other two > nodes are worth to add the information? Yes, I think so. I'd keep each as a separate patch so they can be considered independently. Doing all of them should hopefully ensure we strike the right balance of what code to put in explain.c and what code to put in tuplestore.c. I think the WindowAgg's tuplestore usage pattern might show that the API I picked isn't well suited when a tuplestore is cleared and refilled over and over. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-07-09T06:24:15Z
On Tue, Jul 9, 2024 at 8:20 AM David Rowley <dgrowleyml@gmail.com> wrote: > > On Tue, 9 Jul 2024 at 14:44, Tatsuo Ishii <ishii@postgresql.org> wrote: > > BTW, it seems these executor nodes (other than Materialize and Window > > Aggregate node) use tuplestore for their own purpose. > > > > CTE Scan > > Recursive Union > > Table Function Scan > > > > I have already implemented that for CTE Scan. Do you think other two > > nodes are worth to add the information? > > Yes, I think so. I'd keep each as a separate patch so they can be > considered independently. Doing all of them should hopefully ensure we > strike the right balance of what code to put in explain.c and what > code to put in tuplestore.c. +1 + if (es->format != EXPLAIN_FORMAT_TEXT) + { + ExplainPropertyText("Storage", storageType, es); + ExplainPropertyInteger("Maximum Storage", "kB", spaceUsedKB, es); + } + else + { + ExplainIndentText(es); + appendStringInfo(es->str, + "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n", + storageType, + spaceUsedKB); + } It will be good to move this code to a function which will be called by show_*_info functions(). We might even convert it into a tuplestore specific implementation hook after David's work. -- Best Wishes, Ashutosh Bapat -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-07-09T06:44:09Z
>> Yes, I think so. I'd keep each as a separate patch so they can be >> considered independently. Doing all of them should hopefully ensure we >> strike the right balance of what code to put in explain.c and what >> code to put in tuplestore.c. > +1 > > + if (es->format != EXPLAIN_FORMAT_TEXT) > + { > + ExplainPropertyText("Storage", storageType, es); > + ExplainPropertyInteger("Maximum Storage", "kB", spaceUsedKB, es); > + } > + else > + { > + ExplainIndentText(es); > + appendStringInfo(es->str, > + "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n", > + storageType, > + spaceUsedKB); > + } > > It will be good to move this code to a function which will be called > by show_*_info functions(). I have already implemented that in this direction in my working in progress patch: /* * Show information regarding storage method and maximum memory/disk space * used. */ static void show_storage_info(Tuplestorestate *tupstore, ExplainState *es) Which can be shared by Material and CTE scan node. I am going to post it after I take care Recursive Union and Table Function Scan node. > We might even convert it into a tuplestore > specific implementation hook after David's work. Best reagards, -- Tatsuo Ishii SRA OSS LLC English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-07-10T09:36:10Z
>>> Yes, I think so. I'd keep each as a separate patch so they can be >>> considered independently. Doing all of them should hopefully ensure we >>> strike the right balance of what code to put in explain.c and what >>> code to put in tuplestore.c. >> +1 >> >> + if (es->format != EXPLAIN_FORMAT_TEXT) >> + { >> + ExplainPropertyText("Storage", storageType, es); >> + ExplainPropertyInteger("Maximum Storage", "kB", spaceUsedKB, es); >> + } >> + else >> + { >> + ExplainIndentText(es); >> + appendStringInfo(es->str, >> + "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n", >> + storageType, >> + spaceUsedKB); >> + } >> >> It will be good to move this code to a function which will be called >> by show_*_info functions(). > > I have already implemented that in this direction in my working in > progress patch: Attached are the v2 patches. As suggested by David, I split them into multiple patches so that each patch implements the feature for each node. You need to apply the patches in the order of patch number (if you want to apply all of them, "git apply v2-*.patch" should work). v2-0001-Refactor-show_material_info.patch: This refactors show_material_info(). The guts are moved to new show_storage_info() so that it can be shared by not only Materialized node. v2-0002-Add-memory-disk-usage-for-CTE-Scan-nodes-in-EXPLA.patch: This adds memory/disk usage for CTE Scan nodes in EXPLAIN (ANALYZE) command. v2-0003-Add-memory-disk-usage-for-Table-Function-Scan-nod.patch: This adds memory/disk usage for Table Function Scan nodes in EXPLAIN (ANALYZE) command. v2-0004-Add-memory-disk-usage-for-Recursive-Union-nodes-i.patch: This adds memory/disk usage for Recursive Union nodes in EXPLAIN (ANALYZE) command. Also show_storage_info() is changed so that it accepts int64 storage_used, char *storage_type arguments. They are used if the target node uses multiple tuplestores, in case a simple call to tuplestore_space_used() does not work. Such executor nodes need to collect storage_used while running the node. This type of node includes Recursive Union and Window Aggregate. v2-0005-Add-memory-disk-usage-for-Window-Aggregate-nodes-.patch: This adds memory/disk usage for Window Aggregate nodes in EXPLAIN (ANALYZE) command. Note that if David's proposal https://www.postgresql.org/message-id/CAHoyFK9n-QCXKTUWT_xxtXninSMEv%2BgbJN66-y6prM3f4WkEHw%40mail.gmail.com is committed, this will need to be adjusted. For a demonstration, how storage/memory usage is shown in EXPLAIN (notice "Storage: Memory Maximum Storage: 120kB" etc.). The script used is attached (test.sql.txt). The SQLs are shamelessly copied from David's example and the regression test (some of them were modified by me). EXPLAIN (ANALYZE, COSTS OFF) SELECT count(t1.b) FROM (VALUES(1),(2)) t2(x) LEFT JOIN (SELECT * FROM t1 WHERE a <= 100) t1 ON TRUE; QUERY PLAN --------------------------------------------------------------------------------- Aggregate (actual time=0.345..0.346 rows=1 loops=1) -> Nested Loop Left Join (actual time=0.015..0.330 rows=200 loops=1) -> Values Scan on "*VALUES*" (actual time=0.001..0.003 rows=2 loops=1) -> Materialize (actual time=0.006..0.152 rows=100 loops=2) Storage: Memory Maximum Storage: 120kB -> Seq Scan on t1 (actual time=0.007..0.213 rows=100 loops=1) Filter: (a <= 100) Rows Removed by Filter: 900 Planning Time: 0.202 ms Execution Time: 0.377 ms (10 rows) -- CTE Scan node EXPLAIN (ANALYZE, COSTS OFF) WITH RECURSIVE t(n) AS ( VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 100 ) SELECT sum(n) OVER() FROM t; QUERY PLAN ----------------------------------------------------------------------------------- WindowAgg (actual time=0.151..0.169 rows=100 loops=1) Storage: Memory Maximum Storage: 20kB CTE t -> Recursive Union (actual time=0.001..0.105 rows=100 loops=1) Storage: Memory Maximum Storage: 17kB -> Result (actual time=0.001..0.001 rows=1 loops=1) -> WorkTable Scan on t t_1 (actual time=0.000..0.000 rows=1 loops=100) Filter: (n < 100) Rows Removed by Filter: 0 -> CTE Scan on t (actual time=0.002..0.127 rows=100 loops=1) Storage: Memory Maximum Storage: 20kB Planning Time: 0.053 ms Execution Time: 0.192 ms (13 rows) -- Table Function Scan node CREATE OR REPLACE VIEW public.jsonb_table_view6 AS SELECT js2, jsb2w, jsb2q, ia, ta, jba FROM JSON_TABLE( 'null'::jsonb, '$[*]' AS json_table_path_0 PASSING 1 + 2 AS a, '"foo"'::json AS "b c" COLUMNS ( js2 json PATH '$' WITHOUT WRAPPER KEEP QUOTES, jsb2w jsonb PATH '$' WITH UNCONDITIONAL WRAPPER KEEP QUOTES, jsb2q jsonb PATH '$' WITHOUT WRAPPER OMIT QUOTES, ia integer[] PATH '$' WITHOUT WRAPPER KEEP QUOTES, ta text[] PATH '$' WITHOUT WRAPPER KEEP QUOTES, jba jsonb[] PATH '$' WITHOUT WRAPPER KEEP QUOTES ) ); CREATE VIEW EXPLAIN (ANALYZE, COSTS OFF) SELECT * FROM jsonb_table_view6; QUERY PLAN ------------------------------------------------------------------------------- Table Function Scan on "json_table" (actual time=0.024..0.025 rows=1 loops=1) Storage: Memory Maximum Storage: 17kB Planning Time: 0.100 ms Execution Time: 0.054 ms (4 rows) -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Maxim Orlov <orlovmg@gmail.com> — 2024-09-03T13:53:47Z
Hi! +1 for the idea of the patch. Consider it useful. I looked at the patch set and don't see any obvious defects. It applies without any problems and looks pretty good for me. Only one thing is left to do. Add basic tests for the added functionality to make it committable. For example, as in the mentioned 1eff8279d494b9. -- Best regards, Maxim Orlov.
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-04T00:06:57Z
> Hi! > > +1 for the idea of the patch. Consider it useful. > > I looked at the patch set and don't see any obvious defects. It applies > without any problems and looks pretty good for me. Thank you for reviewing my patch. > Only one thing is left to do. Add basic tests for the added functionality > to make it committable. For example, as in the > mentioned 1eff8279d494b9. Agreed. Probably add to explain.sql? Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Maxim Orlov <orlovmg@gmail.com> — 2024-09-04T05:34:49Z
On Wed, 4 Sept 2024 at 03:07, Tatsuo Ishii <ishii@postgresql.org> wrote: > > Agreed. Probably add to explain.sql? > Yeah, I think this is an appropriate place. -- Best regards, Maxim Orlov.
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
jian he <jian.universality@gmail.com> — 2024-09-04T08:57:00Z
On Wed, Jul 10, 2024 at 5:36 PM Tatsuo Ishii <ishii@postgresql.org> wrote: > > > Attached are the v2 patches. As suggested by David, I split them > into multiple patches so that each patch implements the feature for > each node. You need to apply the patches in the order of patch number > (if you want to apply all of them, "git apply v2-*.patch" should > work). > > v2-0001-Refactor-show_material_info.patch: > This refactors show_material_info(). The guts are moved to new > show_storage_info() so that it can be shared by not only Materialized > node. > > v2-0002-Add-memory-disk-usage-for-CTE-Scan-nodes-in-EXPLA.patch: > This adds memory/disk usage for CTE Scan nodes in EXPLAIN (ANALYZE) command. > > v2-0003-Add-memory-disk-usage-for-Table-Function-Scan-nod.patch: > This adds memory/disk usage for Table Function Scan nodes in EXPLAIN (ANALYZE) command. > > v2-0004-Add-memory-disk-usage-for-Recursive-Union-nodes-i.patch: > This adds memory/disk usage for Recursive Union nodes in EXPLAIN > (ANALYZE) command. Also show_storage_info() is changed so that it > accepts int64 storage_used, char *storage_type arguments. They are > used if the target node uses multiple tuplestores, in case a simple > call to tuplestore_space_used() does not work. Such executor nodes > need to collect storage_used while running the node. This type of node > includes Recursive Union and Window Aggregate. > > v2-0005-Add-memory-disk-usage-for-Window-Aggregate-nodes-.patch: This > adds memory/disk usage for Window Aggregate nodes in EXPLAIN (ANALYZE) > command. Note that if David's proposal > https://www.postgresql.org/message-id/CAHoyFK9n-QCXKTUWT_xxtXninSMEv%2BgbJN66-y6prM3f4WkEHw%40mail.gmail.com > is committed, this will need to be adjusted. > > For a demonstration, how storage/memory usage is shown in EXPLAIN > (notice "Storage: Memory Maximum Storage: 120kB" etc.). The script > used is attached (test.sql.txt). The SQLs are shamelessly copied from > David's example and the regression test (some of them were modified by > me). > hi. I can roughly understand it. I have one minor issue with the comment. typedef struct RecursiveUnionState { PlanState ps; /* its first field is NodeTag */ bool recursing; bool intermediate_empty; Tuplestorestate *working_table; Tuplestorestate *intermediate_table; int64 storageSize; /* max storage size Tuplestore */ char *storageType; /* the storage type above */ .... } "/* the storage type above */" is kind of ambiguous, since there is more than one Tuplestorestate. i think it roughly means: the storage type of working_table while the max storage of working_table. typedef struct WindowAggState { ScanState ss; /* its first field is NodeTag */ /* these fields are filled in by ExecInitExpr: */ List *funcs; /* all WindowFunc nodes in targetlist */ int numfuncs; /* total number of window functions */ int numaggs; /* number that are plain aggregates */ WindowStatePerFunc perfunc; /* per-window-function information */ WindowStatePerAgg peragg; /* per-plain-aggregate information */ ExprState *partEqfunction; /* equality funcs for partition columns */ ExprState *ordEqfunction; /* equality funcs for ordering columns */ Tuplestorestate *buffer; /* stores rows of current partition */ int64 storageSize; /* max storage size in buffer */ char *storageType; /* the storage type above */ } " /* the storage type above */" I think it roughly means: " the storage type of WindowAggState->buffer while the max storage of WindowAggState->buffer". -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-05T04:52:37Z
On Wed, 10 Jul 2024 at 21:36, Tatsuo Ishii <ishii@postgresql.org> wrote: > v2-0005-Add-memory-disk-usage-for-Window-Aggregate-nodes-.patch: This > adds memory/disk usage for Window Aggregate nodes in EXPLAIN (ANALYZE) > command. Note that if David's proposal > https://www.postgresql.org/message-id/CAHoyFK9n-QCXKTUWT_xxtXninSMEv%2BgbJN66-y6prM3f4WkEHw%40mail.gmail.com > is committed, this will need to be adjusted. Hi, I pushed the changes to WindowAgg so as not to call tuplestore_end() on every partition. Can you rebase this patch over that change? It would be good to do this in a way that does not add any new state to WindowAggState, you can see that I had to shuffle fields around in that struct because the next_parition field would have caused the struct to become larger. I've not looked closely, but I expect this can be done by adding more code to tuplestore_updatemax() to also track the disk space used if the current storage has gone to disk. I expect the maxSpace field can be used for both, but we'd need another bool field to track if the max used was by disk or memory. I think the performance of this would also need to be tested as it means doing an lseek() on every tuplestore_clear() when we've gone to disk. Probably that will be dominated by all the other overheads of a tuplestore going to disk (i.e. dumptuples() etc), but it would be good to check this. I suggest setting work_mem = 64 and making a test case that only just spills to disk. Maybe do a few thousand partitions worth of that and see if you can measure any slowdown. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-05T05:38:09Z
Hi, > On Wed, 10 Jul 2024 at 21:36, Tatsuo Ishii <ishii@postgresql.org> wrote: >> v2-0005-Add-memory-disk-usage-for-Window-Aggregate-nodes-.patch: This >> adds memory/disk usage for Window Aggregate nodes in EXPLAIN (ANALYZE) >> command. Note that if David's proposal >> https://www.postgresql.org/message-id/CAHoyFK9n-QCXKTUWT_xxtXninSMEv%2BgbJN66-y6prM3f4WkEHw%40mail.gmail.com >> is committed, this will need to be adjusted. > > Hi, > > I pushed the changes to WindowAgg so as not to call tuplestore_end() > on every partition. Can you rebase this patch over that change? > > It would be good to do this in a way that does not add any new state > to WindowAggState, you can see that I had to shuffle fields around in > that struct because the next_parition field would have caused the > struct to become larger. I've not looked closely, but I expect this > can be done by adding more code to tuplestore_updatemax() to also > track the disk space used if the current storage has gone to disk. I > expect the maxSpace field can be used for both, but we'd need another > bool field to track if the max used was by disk or memory. > > I think the performance of this would also need to be tested as it > means doing an lseek() on every tuplestore_clear() when we've gone to > disk. Probably that will be dominated by all the other overheads of a > tuplestore going to disk (i.e. dumptuples() etc), but it would be good > to check this. I suggest setting work_mem = 64 and making a test case > that only just spills to disk. Maybe do a few thousand partitions > worth of that and see if you can measure any slowdown. Thank you for the suggestion. I will look into this. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-05T06:10:24Z
Hi, > hi. I can roughly understand it. > > I have one minor issue with the comment. > > typedef struct RecursiveUnionState > { > PlanState ps; /* its first field is NodeTag */ > bool recursing; > bool intermediate_empty; > Tuplestorestate *working_table; > Tuplestorestate *intermediate_table; > int64 storageSize; /* max storage size Tuplestore */ > char *storageType; /* the storage type above */ > .... > } > > "/* the storage type above */" > is kind of ambiguous, since there is more than one Tuplestorestate. > > i think it roughly means: the storage type of working_table > while the max storage of working_table. > > > > typedef struct WindowAggState > { > ScanState ss; /* its first field is NodeTag */ > > /* these fields are filled in by ExecInitExpr: */ > List *funcs; /* all WindowFunc nodes in targetlist */ > int numfuncs; /* total number of window functions */ > int numaggs; /* number that are plain aggregates */ > > WindowStatePerFunc perfunc; /* per-window-function information */ > WindowStatePerAgg peragg; /* per-plain-aggregate information */ > ExprState *partEqfunction; /* equality funcs for partition columns */ > ExprState *ordEqfunction; /* equality funcs for ordering columns */ > Tuplestorestate *buffer; /* stores rows of current partition */ > int64 storageSize; /* max storage size in buffer */ > char *storageType; /* the storage type above */ > } > > " /* the storage type above */" > I think it roughly means: > " the storage type of WindowAggState->buffer while the max storage of > WindowAggState->buffer". Thank you for looking into my patch. Unfortunately I need to work on other issue before adjusting the comments because the fields might go away if I change the tuplestore infrastructure per David's suggestion: https://www.postgresql.org/message-id/CAApHDvoY8cibGcicLV0fNh%3D9JVx9PANcWvhkdjBnDCc9Quqytg%40mail.gmail.com After this I will rebase the patches. This commit requires changes. https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=908a968612f9ed61911d8ca0a185b262b82f1269 Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-06T04:21:31Z
Hi David, >> I pushed the changes to WindowAgg so as not to call tuplestore_end() >> on every partition. Can you rebase this patch over that change? >> >> It would be good to do this in a way that does not add any new state >> to WindowAggState, you can see that I had to shuffle fields around in >> that struct because the next_parition field would have caused the >> struct to become larger. I've not looked closely, but I expect this >> can be done by adding more code to tuplestore_updatemax() to also >> track the disk space used if the current storage has gone to disk. I >> expect the maxSpace field can be used for both, but we'd need another >> bool field to track if the max used was by disk or memory. I have created a patch in the direction you suggested. See attached patch (v1-0001-Enhance-tuplestore.txt). To not confuse CFbot, the extension is "txt", not "patch". >> I think the performance of this would also need to be tested as it >> means doing an lseek() on every tuplestore_clear() when we've gone to >> disk. Probably that will be dominated by all the other overheads of a >> tuplestore going to disk (i.e. dumptuples() etc), but it would be good >> to check this. I suggest setting work_mem = 64 and making a test case >> that only just spills to disk. Maybe do a few thousand partitions >> worth of that and see if you can measure any slowdown. I copied your shell script and slightly modified it then ran pgbench with (1 10 100 1000 5000 10000) window partitions (see attached shell script). In the script I set work_mem to 64kB. It seems for 10000, 1000 and 100 partitions, the performance difference seems noises. However, for 10, 2, 1 partitions. I see large performance degradation with the patched version: patched is slower than stock master in 1.5% (10 partitions), 41% (2 partitions) and 55.7% (1 partition). See the attached graph.
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-06T05:07:48Z
On Fri, 6 Sept 2024 at 16:21, Tatsuo Ishii <ishii@postgresql.org> wrote: > However, for 10, 2, 1 partitions. I see large performance > degradation with the patched version: patched is slower than stock > master in 1.5% (10 partitions), 41% (2 partitions) and 55.7% (1 > partition). See the attached graph. Thanks for making the adjustments to this. I don't think there is any need to call tuplestore_updatemax() from within writetup_heap(). That means having to update the maximum space used every time a tuple is written to disk. That's a fairly massive overhead. Instead, it should be fine to modify tuplestore_updatemax() to set a flag to true if state->status != TSS_INMEM and then record the disk space used. That flag won't ever be set to false again. tuplestore_storage_type_name() should just return "Disk" if the new disk flag is set, even if state->status == TSS_INMEM. Since the work_mem size won't change between tuplestore_clear() calls, if we've once spilt to disk, then we shouldn't care about the memory used for runs that didn't. Those will always have used less memory. I did this quickly, but playing around with the attached, I didn't see any slowdown. Here's the results I got on my Zen2 AMD machine: parts master yours mine mine_v_master 10000 5.01 5.12 5.09 99% 1000 4.30 4.25 4.24 101% 100 4.17 4.13 4.12 101% 10 4.16 4.12 4.10 101% 2 4.75 7.64 4.73 100% 1 4.75 8.57 4.73 100% David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-06T06:02:37Z
> Thanks for making the adjustments to this. > > I don't think there is any need to call tuplestore_updatemax() from > within writetup_heap(). That means having to update the maximum space > used every time a tuple is written to disk. That's a fairly massive > overhead. > > Instead, it should be fine to modify tuplestore_updatemax() to set a > flag to true if state->status != TSS_INMEM and then record the disk > space used. That flag won't ever be set to false again. > tuplestore_storage_type_name() should just return "Disk" if the new > disk flag is set, even if state->status == TSS_INMEM. Since the > work_mem size won't change between tuplestore_clear() calls, if we've > once spilt to disk, then we shouldn't care about the memory used for > runs that didn't. Those will always have used less memory. > > I did this quickly, but playing around with the attached, I didn't see > any slowdown. Your patch looks good to me and I confirmed that with your patch I didn't see any slowdown either. Thanks! Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-09-06T07:07:55Z
On Fri, Sep 6, 2024 at 11:32 AM Tatsuo Ishii <ishii@postgresql.org> wrote: > > > Thanks for making the adjustments to this. > > > > I don't think there is any need to call tuplestore_updatemax() from > > within writetup_heap(). That means having to update the maximum space > > used every time a tuple is written to disk. That's a fairly massive > > overhead. > > > > Instead, it should be fine to modify tuplestore_updatemax() to set a > > flag to true if state->status != TSS_INMEM and then record the disk > > space used. That flag won't ever be set to false again. > > tuplestore_storage_type_name() should just return "Disk" if the new > > disk flag is set, even if state->status == TSS_INMEM. Since the > > work_mem size won't change between tuplestore_clear() calls, if we've > > once spilt to disk, then we shouldn't care about the memory used for > > runs that didn't. Those will always have used less memory. > > > > I did this quickly, but playing around with the attached, I didn't see > > any slowdown. > > Your patch looks good to me and I confirmed that with your patch I > didn't see any slowdown either. Thanks! The changes look better. A nitpick though. With their definitions changed, I think it's better to change the names of the functions since their purpose has changed. Right now they report the storage type and size used, respectively, at the time of calling the function. With this patch, they report maximum space ever used and the storage corresponding to the maximum space. tuplestore_space_used() may be changed to tuplestore_maxspace_used(). I am having difficulty with tuplestore_storage_type_name(); tuplestore_largest_storage_type_name() seems mouthful and yet not doing justice to the functionality. It might be better to just have one funciton tuplestore_maxspace_used() which returns both the maximum space used as well as the storage type when maximum space was used. The comments need a bit of grammar fixes, but that can be done when finalizing the patches. -- Best Wishes, Ashutosh Bapat
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-06T07:50:30Z
> The changes look better. A nitpick though. With their definitions > changed, I think it's better to change the names of the functions > since their purpose has changed. Right now they report the storage > type and size used, respectively, at the time of calling the function. > With this patch, they report maximum space ever used and the storage > corresponding to the maximum space. tuplestore_space_used() may be > changed to tuplestore_maxspace_used(). I am having difficulty with > tuplestore_storage_type_name(); tuplestore_largest_storage_type_name() > seems mouthful and yet not doing justice to the functionality. It > might be better to just have one funciton tuplestore_maxspace_used() > which returns both the maximum space used as well as the storage type > when maximum space was used. +1. Returning the storage type by the same function, not by a separate function looks more natural. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-06T13:51:34Z
On Fri, 6 Sept 2024 at 19:08, Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> wrote: > The changes look better. A nitpick though. With their definitions > changed, I think it's better to change the names of the functions > since their purpose has changed. Right now they report the storage > type and size used, respectively, at the time of calling the function. > With this patch, they report maximum space ever used and the storage > corresponding to the maximum space. tuplestore_space_used() may be > changed to tuplestore_maxspace_used(). I am having difficulty with > tuplestore_storage_type_name(); tuplestore_largest_storage_type_name() > seems mouthful and yet not doing justice to the functionality. It > might be better to just have one funciton tuplestore_maxspace_used() > which returns both the maximum space used as well as the storage type > when maximum space was used. How about just removing tuplestore_storage_type_name() and tuplestore_space_used() and adding tuplestore_get_stats(). I did take some inspiration from tuplesort.c for this, so maybe we can defer back there for further guidance. I'm not so sure it's worth having a stats struct type like tuplesort.c has. All we need is a char ** and an int64 * output parameter to pass to the stats function. I don't think we need to copy the tuplesort_method_name(). It seems fine just to point the output parameter of the stats function at the statically allocated constant. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-09-09T10:12:34Z
On Fri, Sep 6, 2024 at 7:21 PM David Rowley <dgrowleyml@gmail.com> wrote: > > On Fri, 6 Sept 2024 at 19:08, Ashutosh Bapat > <ashutosh.bapat.oss@gmail.com> wrote: > > The changes look better. A nitpick though. With their definitions > > changed, I think it's better to change the names of the functions > > since their purpose has changed. Right now they report the storage > > type and size used, respectively, at the time of calling the function. > > With this patch, they report maximum space ever used and the storage > > corresponding to the maximum space. tuplestore_space_used() may be > > changed to tuplestore_maxspace_used(). I am having difficulty with > > tuplestore_storage_type_name(); tuplestore_largest_storage_type_name() > > seems mouthful and yet not doing justice to the functionality. It > > might be better to just have one funciton tuplestore_maxspace_used() > > which returns both the maximum space used as well as the storage type > > when maximum space was used. > > How about just removing tuplestore_storage_type_name() and > tuplestore_space_used() and adding tuplestore_get_stats(). I did take > some inspiration from tuplesort.c for this, so maybe we can defer back > there for further guidance. I'm not so sure it's worth having a stats > struct type like tuplesort.c has. All we need is a char ** and an > int64 * output parameter to pass to the stats function. I don't think > we need to copy the tuplesort_method_name(). It seems fine just to > point the output parameter of the stats function at the statically > allocated constant. tuplestore_get_stats() similar to tuplesort_get_stats() looks fine. In future the stats reported by this function might expand e.g. maximum number of readers may be included in the stats. If it expands beyond two values, we could think of a separate structure, but for now it looks fine given its limited use. A comment explaining why we aren't using a stats structure and some guidance on when that would be appropriate will be better. -- Best Wishes, Ashutosh Bapat
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-12T02:03:54Z
> On Fri, 6 Sept 2024 at 19:08, Ashutosh Bapat > <ashutosh.bapat.oss@gmail.com> wrote: >> The changes look better. A nitpick though. With their definitions >> changed, I think it's better to change the names of the functions >> since their purpose has changed. Right now they report the storage >> type and size used, respectively, at the time of calling the function. >> With this patch, they report maximum space ever used and the storage >> corresponding to the maximum space. tuplestore_space_used() may be >> changed to tuplestore_maxspace_used(). I am having difficulty with >> tuplestore_storage_type_name(); tuplestore_largest_storage_type_name() >> seems mouthful and yet not doing justice to the functionality. It >> might be better to just have one funciton tuplestore_maxspace_used() >> which returns both the maximum space used as well as the storage type >> when maximum space was used. > > How about just removing tuplestore_storage_type_name() and > tuplestore_space_used() and adding tuplestore_get_stats(). I did take > some inspiration from tuplesort.c for this, so maybe we can defer back > there for further guidance. I'm not so sure it's worth having a stats > struct type like tuplesort.c has. All we need is a char ** and an > int64 * output parameter to pass to the stats function. I don't think > we need to copy the tuplesort_method_name(). It seems fine just to > point the output parameter of the stats function at the statically > allocated constant. Are you going to push the changes to tuplestore.c anytime soon? I would like to rebase my patch[1] but the patch could be affected by the tuplestore API change. Best reagards, [1] https://www.postgresql.org/message-id/CAApHDvoY8cibGcicLV0fNh%3D9JVx9PANcWvhkdjBnDCc9Quqytg%40mail.gmail.com -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-12T02:28:14Z
On Thu, 12 Sept 2024 at 14:04, Tatsuo Ishii <ishii@postgresql.org> wrote: > Are you going to push the changes to tuplestore.c anytime soon? I > would like to rebase my patch[1] but the patch could be affected by > the tuplestore API change. Ok, I'll look at that. I had thought you were taking care of writing the patch. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-12T02:42:06Z
> On Thu, 12 Sept 2024 at 14:04, Tatsuo Ishii <ishii@postgresql.org> wrote: >> Are you going to push the changes to tuplestore.c anytime soon? I >> would like to rebase my patch[1] but the patch could be affected by >> the tuplestore API change. > > Ok, I'll look at that. Thanks. I had thought you were taking care of writing the patch. Sorry, I should have asked you first if you are going to write the API change patch. -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-12T05:07:23Z
On Thu, 12 Sept 2024 at 14:42, Tatsuo Ishii <ishii@postgresql.org> wrote: > Sorry, I should have asked you first if you are going to write the API > change patch. I pushed a patch to change the API. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-12T05:09:59Z
> I pushed a patch to change the API. Thank you! -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-12T12:12:06Z
Here is the v3 patch. This time I only include patch for the Window Aggregate node. Patches for other node types will come after this patch getting committed or come close to commitable state. David, In this patch I refactored show_material_info. I divided it into show_material_info and show_storage_info so that the latter can be used by other node types including window aggregate node. What do you think? I also added a test case in explain.sql per discussion with Maxim Orlov. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-12T21:20:11Z
On Fri, 13 Sept 2024 at 00:12, Tatsuo Ishii <ishii@postgresql.org> wrote: > In this patch I refactored show_material_info. I divided it into > show_material_info and show_storage_info so that the latter can be > used by other node types including window aggregate node. What do you > think? Yes, I think it's a good idea to move that into a helper function. If you do the other node types, without that helper the could would have to be repeated quite a few times. Maybe show_storage_info() can be moved up with the other helper functions, say below show_sortorder_options() ? It might be a good idea to keep the "if (!es->analyze || tupstore == NULL)" checks in the calling function rather than the helper too. I thought about the location of the test for a while and read the "This file is concerned with testing EXPLAIN in its own right." comment at the top of that explain.out. I was trying to decide if testing output of a specific node type met this or not. I can't pick out any other tests there which are specific to a node type, so I'm unsure if this is the location for it or not. However, to put it anywhere else means having to add a plpgsql function to mask out the unstable parts of EXPLAIN, so maybe the location is good as it saves from having to do that. I'm 50/50 on this, so I'm happy to let you decide. You could also shrink that 100 rows into a smaller number for the generate_series without losing any coverage. Aside from that, I think the patch is good. Thanks for working on it. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-13T06:11:33Z
David, Thank you for your review. > Yes, I think it's a good idea to move that into a helper function. If > you do the other node types, without that helper the could would have > to be repeated quite a few times. Maybe show_storage_info() can be > moved up with the other helper functions, say below > show_sortorder_options() ? Yeah, that makes sense. Looks less random. > It might be a good idea to keep the "if > (!es->analyze || tupstore == NULL)" checks in the calling function > rather than the helper too. I agree with this. This kind of check should be done in the calling function. > I thought about the location of the test for a while and read the > "This file is concerned with testing EXPLAIN in its own right." > comment at the top of that explain.out. I was trying to decide if > testing output of a specific node type met this or not. I can't pick > out any other tests there which are specific to a node type, so I'm > unsure if this is the location for it or not. However, to put it > anywhere else means having to add a plpgsql function to mask out the > unstable parts of EXPLAIN, so maybe the location is good as it saves > from having to do that. I'm 50/50 on this, so I'm happy to let you > decide. Yeah. Maybe we should move the function to elsewhere so that it can be shared by other tests. However in this case it's purpose is testing an additional output in an explain command. I think this is not far from "This file is concerned with testing EXPLAIN in its own right.". So I would like to keep the test in explain.sql. > You could also shrink that 100 rows into a smaller number for > the generate_series without losing any coverage. Right. I will make the change. > Aside from that, I think the patch is good. Thanks for working on it. Thanks. Attached is the v4 patch. I am going push it if there's no objection. After this, I will work on remaining node types. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Maxim Orlov <orlovmg@gmail.com> — 2024-09-13T08:57:25Z
On Fri, 13 Sept 2024 at 09:11, Tatsuo Ishii <ishii@postgresql.org> wrote: > Thanks. Attached is the v4 patch. I am going push it if there's no > objection. > Looks good to me. Thank you for your work. -- Best regards, Maxim Orlov.
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-09-13T09:06:41Z
The patch looks fine but it doesn't add a test case where Storage is Disk or the case when the last usage fit in memory but an earlier usage spilled to disk. Do we want to cover those. This test would be the only one where those code paths could be tested. On Fri, Sep 13, 2024 at 11:41 AM Tatsuo Ishii <ishii@postgresql.org> wrote: > > David, > > Thank you for your review. > > > Yes, I think it's a good idea to move that into a helper function. If > > you do the other node types, without that helper the could would have > > to be repeated quite a few times. Maybe show_storage_info() can be > > moved up with the other helper functions, say below > > show_sortorder_options() ? > > Yeah, that makes sense. Looks less random. > > > It might be a good idea to keep the "if > > (!es->analyze || tupstore == NULL)" checks in the calling function > > rather than the helper too. > > I agree with this. This kind of check should be done in the calling > function. > > > I thought about the location of the test for a while and read the > > "This file is concerned with testing EXPLAIN in its own right." > > comment at the top of that explain.out. I was trying to decide if > > testing output of a specific node type met this or not. I can't pick > > out any other tests there which are specific to a node type, so I'm > > unsure if this is the location for it or not. However, to put it > > anywhere else means having to add a plpgsql function to mask out the > > unstable parts of EXPLAIN, so maybe the location is good as it saves > > from having to do that. I'm 50/50 on this, so I'm happy to let you > > decide. > > Yeah. Maybe we should move the function to elsewhere so that it can be > shared by other tests. However in this case it's purpose is testing an > additional output in an explain command. I think this is not far from > "This file is concerned with testing EXPLAIN in its own right.". So I > would like to keep the test in explain.sql. > > > You could also shrink that 100 rows into a smaller number for > > the generate_series without losing any coverage. > > Right. I will make the change. > > > Aside from that, I think the patch is good. Thanks for working on it. > > Thanks. Attached is the v4 patch. I am going push it if there's no > objection. > > After this, I will work on remaining node types. > > Best reagards, > -- > Tatsuo Ishii > SRA OSS K.K. > English: http://www.sraoss.co.jp/index_en/ > Japanese:http://www.sraoss.co.jp -- Best Wishes, Ashutosh Bapat
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-13T09:31:53Z
> The patch looks fine but it doesn't add a test case where Storage is > Disk We can test the case by setting work_mem to the minimum size (64kB) and giving slightly larger "stop" parameter to generate_series. > or the case when the last usage fit in memory but an earlier > usage spilled to disk. In my understanding once tuplestore changes the storage type to disk, it never returns to the memory storage type in terms of tuplestore_get_stats. i.e. once state->usedDisk is set to true, it never goes back to false. So the test case is not necessary. David, am I correct? > Do we want to cover those. This test would be > the only one where those code paths could be tested. I am fine to add the first test case. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-09-13T10:44:04Z
On Fri, Sep 13, 2024 at 3:02 PM Tatsuo Ishii <ishii@postgresql.org> wrote: > > > The patch looks fine but it doesn't add a test case where Storage is > > Disk > > We can test the case by setting work_mem to the minimum size (64kB) > and giving slightly larger "stop" parameter to generate_series. > WFM > > or the case when the last usage fit in memory but an earlier > > usage spilled to disk. > > In my understanding once tuplestore changes the storage type to disk, > it never returns to the memory storage type in terms of > tuplestore_get_stats. i.e. once state->usedDisk is set to true, it > never goes back to false. So the test case is not necessary. > David, am I correct? I understand that. I am requesting a testcase to test that same logic. -- Best Wishes, Ashutosh Bapat
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-14T08:12:01Z
>> > or the case when the last usage fit in memory but an earlier >> > usage spilled to disk. >> >> In my understanding once tuplestore changes the storage type to disk, >> it never returns to the memory storage type in terms of >> tuplestore_get_stats. i.e. once state->usedDisk is set to true, it >> never goes back to false. So the test case is not necessary. >> David, am I correct? > > I understand that. I am requesting a testcase to test that same logic. Maybe something like this? In the example below there are 2 partitions. the first one has 1998 rows and the second one has 2 rows. Assuming that work_mem is 64kB, the first one does not fit the memory and spills to disk. The second partition fits memory. However as state->usedDisk remains true, explain shows "Storage: Disk". test=# explain (analyze,costs off) select sum(n) over(partition by m) from (SELECT n < 3 as m, n from generate_series(1,2000) a(n)); n QUERY PLAN -------------------------------------------------------------------------------- ------------- WindowAgg (actual time=1.958..473328.589 rows=2000 loops=1) Storage: Disk Maximum Storage: 65kB -> Sort (actual time=1.008..1.277 rows=2000 loops=1) Sort Key: ((a.n < 3)) Sort Method: external merge Disk: 48kB -> Function Scan on generate_series a (actual time=0.300..0.633 rows=2 000 loops=1) Planning Time: 0.069 ms Execution Time: 474515.476 ms (8 rows) Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-09-16T11:11:17Z
On Sat, Sep 14, 2024 at 1:42 PM Tatsuo Ishii <ishii@postgresql.org> wrote: > > >> > or the case when the last usage fit in memory but an earlier > >> > usage spilled to disk. > >> > >> In my understanding once tuplestore changes the storage type to disk, > >> it never returns to the memory storage type in terms of > >> tuplestore_get_stats. i.e. once state->usedDisk is set to true, it > >> never goes back to false. So the test case is not necessary. > >> David, am I correct? > > > > I understand that. I am requesting a testcase to test that same logic. > > Maybe something like this? In the example below there are 2 > partitions. the first one has 1998 rows and the second one has 2 > rows. Assuming that work_mem is 64kB, the first one does not fit the > memory and spills to disk. The second partition fits memory. However as > state->usedDisk remains true, explain shows "Storage: Disk". > > test=# explain (analyze,costs off) select sum(n) over(partition by m) from (SELECT n < 3 as m, n from generate_series(1,2000) a(n)); > n QUERY PLAN > > -------------------------------------------------------------------------------- > ------------- > WindowAgg (actual time=1.958..473328.589 rows=2000 loops=1) > Storage: Disk Maximum Storage: 65kB > -> Sort (actual time=1.008..1.277 rows=2000 loops=1) > Sort Key: ((a.n < 3)) > Sort Method: external merge Disk: 48kB > -> Function Scan on generate_series a (actual time=0.300..0.633 rows=2 > 000 loops=1) > Planning Time: 0.069 ms > Execution Time: 474515.476 ms > (8 rows) Thanks. This will do. Is there a way to force the larger partition to be computed first? That way we definitely know that the last computation was done when all the tuples in the tuplestore were in memory. -- Best Wishes, Ashutosh Bapat
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-16T12:13:17Z
Hi Ashutosh, Thank you for the review. > Thanks. This will do. Is there a way to force the larger partition to > be computed first? That way we definitely know that the last > computation was done when all the tuples in the tuplestore were in > memory. Not sure if there's any way to force it in the SQL standard. However in term of implementation, PostgreSQL sorts the function (generate_series) scan result using a sort key "a.n < 3", which results in rows being >= 2 first (as false == 0), then rows being < 3 (as true == 1). So unless PostgreSQL changes the way to sort boolean data type, I think the result should be stable. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-17T02:40:04Z
> Not sure if there's any way to force it in the SQL standard. However > in term of implementation, PostgreSQL sorts the function > (generate_series) scan result using a sort key "a.n < 3", which > results in rows being >= 2 first (as false == 0), then rows being < 3 > (as true == 1). So unless PostgreSQL changes the way to sort boolean > data type, I think the result should be stable. Attached is the v5 patch. The difference from v4 is addtion of two more tests to explain.sql: 1) spils to disk case 2) splis to disk then switch back to memory case Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-17T03:16:09Z
On Tue, 17 Sept 2024 at 14:40, Tatsuo Ishii <ishii@postgresql.org> wrote: > Attached is the v5 patch. The difference from v4 is addtion of two > more tests to explain.sql: > > 1) spils to disk case > 2) splis to disk then switch back to memory case Looks ok to me, aside from the missing "reset work_mem;" after you're done with testing the disk spilling code. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-17T06:06:26Z
> On Tue, 17 Sept 2024 at 14:40, Tatsuo Ishii <ishii@postgresql.org> wrote: >> Attached is the v5 patch. The difference from v4 is addtion of two >> more tests to explain.sql: >> >> 1) spils to disk case >> 2) splis to disk then switch back to memory case > > Looks ok to me, aside from the missing "reset work_mem;" after you're > done with testing the disk spilling code. Thanks. I have added it and pushed the patch. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-18T12:12:46Z
> Thanks. I have added it and pushed the patch. So I have created patches to do the same for CTE scan and table function scan node. Patch attached. Actually there's one more executor node type that uses tuplestore: recursive union (used in "with recursive"). The particular node type uses two tuplestore and we cannot simply apply tuplestore_get_stats() to the node type. We need to modify RecursiveUnionState to track the maximum tuplestore usage. I am not sure this would be worth the effort. Opinion? Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-18T21:57:51Z
On Thu, 19 Sept 2024 at 00:13, Tatsuo Ishii <ishii@postgresql.org> wrote: > Actually there's one more executor node type that uses tuplestore: > recursive union (used in "with recursive"). The particular node type > uses two tuplestore and we cannot simply apply tuplestore_get_stats() > to the node type. We need to modify RecursiveUnionState to track the > maximum tuplestore usage. I am not sure this would be worth the > effort. Opinion? Could you add the two sizes together and take the storage type from the tuplestore with the highest storage size? David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-19T00:01:34Z
> On Thu, 19 Sept 2024 at 00:13, Tatsuo Ishii <ishii@postgresql.org> wrote: >> Actually there's one more executor node type that uses tuplestore: >> recursive union (used in "with recursive"). The particular node type >> uses two tuplestore and we cannot simply apply tuplestore_get_stats() >> to the node type. We need to modify RecursiveUnionState to track the >> maximum tuplestore usage. I am not sure this would be worth the >> effort. Opinion? > > Could you add the two sizes together and take the storage type from > the tuplestore with the highest storage size? I don't think this works because tuplestore_begin/tuplestore_end are called while executing the node (ExecRecursiveUnion). I think the way you are proposing only shows the stats last time when those tuplestore are created. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-19T00:49:31Z
On Thu, 19 Sept 2024 at 12:01, Tatsuo Ishii <ishii@postgresql.org> wrote: > > Could you add the two sizes together and take the storage type from > > the tuplestore with the highest storage size? > > I don't think this works because tuplestore_begin/tuplestore_end are > called while executing the node (ExecRecursiveUnion). > > I think the way you are proposing only shows the stats last time when > those tuplestore are created. That code could be modified to swap the tuplestores and do a tuplestore_clear() instead of tuplestore_end() followed by tuplestore_begin_heap(). It's likely worthwhile from a performance point of view. Here's a small test as an example: master: postgres=# with recursive cte (a) as (select 1 union all select cte.a+1 from cte where cte.a+1 <= 1000000) select count(*) from cte; Time: 219.023 ms Time: 218.828 ms Time: 219.093 ms with attached patched: postgres=# with recursive cte (a) as (select 1 union all select cte.a+1 from cte where cte.a+1 <= 1000000) select count(*) from cte; Time: 169.734 ms Time: 164.841 ms Time: 169.168 ms David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-19T01:49:17Z
> That code could be modified to swap the tuplestores and do a > tuplestore_clear() instead of tuplestore_end() followed by > tuplestore_begin_heap(). > > It's likely worthwhile from a performance point of view. Here's a > small test as an example: > > master: > postgres=# with recursive cte (a) as (select 1 union all select > cte.a+1 from cte where cte.a+1 <= 1000000) select count(*) from cte; > Time: 219.023 ms > Time: 218.828 ms > Time: 219.093 ms > > with attached patched: > postgres=# with recursive cte (a) as (select 1 union all select > cte.a+1 from cte where cte.a+1 <= 1000000) select count(*) from cte; > Time: 169.734 ms > Time: 164.841 ms > Time: 169.168 ms Impressive result. I also ran your query with count 1000. without the patch: Time: 3.655 ms Time: 4.123 ms Time: 2.163 ms wit the patch: Time: 3.641 ms Time: 2.356 ms Time: 2.347 ms It seems with the patch the performance is slightly better or almost same. I think the patch improves the performance without sacrificing the smaller iteration case. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-19T02:11:05Z
On Thu, 19 Sept 2024 at 13:49, Tatsuo Ishii <ishii@postgresql.org> wrote: > I also ran your query with count 1000. > > without the patch: > Time: 3.655 ms > Time: 4.123 ms > Time: 2.163 ms > > wit the patch: > Time: 3.641 ms > Time: 2.356 ms > Time: 2.347 ms > > It seems with the patch the performance is slightly better or almost > same. I think the patch improves the performance without sacrificing > the smaller iteration case. You might need to use pgbench to get more stable results with such a small test. If your CPU clocks down when idle, it's not going to clock up as fast as you might like it to when you give it something to do. Here's what I got when running 1000 iterations: $ cat bench.sql with recursive cte (a) as (select 1 union all select cte.a+1 from cte where cte.a+1 <= 1000) select count(*) from cte; master $ for i in {1..5}; do pgbench -n -f bench.sql -T 10 -M prepared postgres | grep latency; done latency average = 0.251 ms latency average = 0.254 ms latency average = 0.251 ms latency average = 0.252 ms latency average = 0.253 ms patched $ for i in {1..5}; do pgbench -n -f bench.sql -T 10 -M prepared postgres | grep latency; done latency average = 0.202 ms latency average = 0.202 ms latency average = 0.207 ms latency average = 0.202 ms latency average = 0.202 ms (~24.2% faster) David -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-19T03:22:11Z
On Thu, 19 Sept 2024 at 13:49, Tatsuo Ishii <ishii@postgresql.org> wrote: > > > That code could be modified to swap the tuplestores and do a > > tuplestore_clear() instead of tuplestore_end() followed by > > tuplestore_begin_heap(). > > > Impressive result. I also ran your query with count 1000. I've pushed that patch. That should now unblock you on the nodeRecursiveunion.c telemetry. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-19T04:21:40Z
>> > That code could be modified to swap the tuplestores and do a >> > tuplestore_clear() instead of tuplestore_end() followed by >> > tuplestore_begin_heap(). >> > >> Impressive result. I also ran your query with count 1000. > > I've pushed that patch. That should now unblock you on the > nodeRecursiveunion.c telemetry. Thanks. Attached is a patch for CTE scan, table function scan and recursive union scan nodes. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-19T05:37:06Z
On Thu, 19 Sept 2024 at 16:21, Tatsuo Ishii <ishii@postgresql.org> wrote: > Thanks. Attached is a patch for CTE scan, table function scan and > recursive union scan nodes. 1. It's probably a minor detail, but in show_recursive_union_info(), I don't think the tuplestores can ever be NULL. + if (working_table != NULL) + tuplestore_get_stats(working_table, &tempStorageType, &tempSpaceUsed); + + if (intermediate_table != NULL) + tuplestore_get_stats(intermediate_table, &maxStorageType, &maxSpaceUsed); I added the NULL tests for the Materialize case as the tuplestore is created in ExecMaterial() rather than ExecInitMaterial(). For the two tuplestorestates above, they're both created in ExecInitRecursiveUnion(). 2. I imagined you'd always do maxSpaceUsed += tempSpaceUsed; or maxSpaceUsedKB = BYTES_TO_KILOBYTES(maxSpaceUsed + tempSpaceUsed); + if (tempSpaceUsed > maxSpaceUsed) + { + maxStorageType = tempStorageType; + maxSpaceUsed = tempSpaceUsed; + } Why do you think the the space used by the smaller tuplestore should be ignored in the storage size output? David -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-19T10:17:40Z
> 1. It's probably a minor detail, but in show_recursive_union_info(), I > don't think the tuplestores can ever be NULL. > > + if (working_table != NULL) > + tuplestore_get_stats(working_table, &tempStorageType, &tempSpaceUsed); > + > + if (intermediate_table != NULL) > + tuplestore_get_stats(intermediate_table, &maxStorageType, &maxSpaceUsed); > > I added the NULL tests for the Materialize case as the tuplestore is > created in ExecMaterial() rather than ExecInitMaterial(). For the two > tuplestorestates above, they're both created in > ExecInitRecursiveUnion(). You are right. Also I checked other Exec* in nodeRecursiveunion.c and did not find any place where working_table and intermediate_table are set to NULL. > 2. I imagined you'd always do maxSpaceUsed += tempSpaceUsed; or > maxSpaceUsedKB = BYTES_TO_KILOBYTES(maxSpaceUsed + tempSpaceUsed); > > + if (tempSpaceUsed > maxSpaceUsed) > + { > + maxStorageType = tempStorageType; > + maxSpaceUsed = tempSpaceUsed; > + } > > Why do you think the the space used by the smaller tuplestore should > be ignored in the storage size output? I thought about the case when the two tuplestores have different storage types. But I remember that we already use disk storage type even if the storage type was changed from disk to memory[1]. So probably we don't need to much worry about the storage kind difference in the two tuplestores. Attached patch fixes 1 & 2. [1] https://www.postgresql.org/message-id/CAExHW5vRPRLvsZYLmNGcDLkPDWDHXGSWYjox-to-OsCVFETd3w%40mail.gmail.com Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp -
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-22T23:55:07Z
On Thu, 19 Sept 2024 at 22:17, Tatsuo Ishii <ishii@postgresql.org> wrote: > Attached patch fixes 1 & 2. I looked at this and thought that one thing you might want to consider is adjusting show_storage_info() to accept the size and type parameters so you don't have to duplicate the formatting code in show_recursive_union_info(). The first of the new tests also isn't testing what you want it to test. Maybe you could add a "materialized" in there to stop the CTE being inlined: explain (analyze,costs off) with w(n) as materialized (select n from generate_series(1,10) a(n)) select sum(n) from w Also, I'm on the fence about if the new tests are worthwhile. I won't object to them, however. I just wanted to note that most of the complexity is in tuplestore.c of which there's already coverage for. The test's value is reduced by the fact that most of the interesting details have to be masked out due to possible platform variations in the number of bytes. Really the new tests are only testing that we display the storage details and maybe that the storage type came out as expected. It seems unlikely these would get broken. I'd say it's committers preference, however. I just wanted to add my thoughts. You have to offset the value against the fact that the expected output is likely to change over the years which adds to the burden of making changes to the EXPLAIN output. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-23T06:28:32Z
> I looked at this and thought that one thing you might want to consider > is adjusting show_storage_info() to accept the size and type > parameters so you don't have to duplicate the formatting code in > show_recursive_union_info(). I agree and made necessary changes. See attached v4 patches. > The first of the new tests also isn't testing what you want it to > test. Maybe you could add a "materialized" in there to stop the CTE > being inlined: > > explain (analyze,costs off) with w(n) as materialized (select n from > generate_series(1,10) a(n)) select sum(n) from w > > Also, I'm on the fence about if the new tests are worthwhile. I won't > object to them, however. I just wanted to note that most of the > complexity is in tuplestore.c of which there's already coverage for. > The test's value is reduced by the fact that most of the interesting > details have to be masked out due to possible platform variations in > the number of bytes. Really the new tests are only testing that we > display the storage details and maybe that the storage type came out > as expected. It seems unlikely these would get broken. I'd say it's > committers preference, however. I just wanted to add my thoughts. You > have to offset the value against the fact that the expected output is > likely to change over the years which adds to the burden of making > changes to the EXPLAIN output. After thinking more, I lean toward to your opinion. The new tests do not give big value, but on the other hand they could become a burden over the years. I do not include the new tests in the v4 patches. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
David Rowley <dgrowleyml@gmail.com> — 2024-09-23T07:05:25Z
On Mon, 23 Sept 2024 at 18:28, Tatsuo Ishii <ishii@postgresql.org> wrote: > I agree and made necessary changes. See attached v4 patches. Looks good to me. David
-
Re: Add memory/disk usage for WindowAgg nodes in EXPLAIN
Tatsuo Ishii <ishii@postgresql.org> — 2024-09-23T07:52:39Z
> On Mon, 23 Sept 2024 at 18:28, Tatsuo Ishii <ishii@postgresql.org> wrote: >> I agree and made necessary changes. See attached v4 patches. > > Looks good to me. Thank you for the review! I have pushed the patch. Best reagards, -- Tatsuo Ishii SRA OSS K.K. English: http://www.sraoss.co.jp/index_en/ Japanese:http://www.sraoss.co.jp