Thread

Commits

  1. Add memory/disk usage for more executor nodes.

  2. Optimize tuplestore usage for WITH RECURSIVE CTEs

  3. Add memory/disk usage for Window aggregate nodes in EXPLAIN.

  4. Optimize WindowAgg's use of tuplestores

  1. 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
    
  2. 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
    
    
    
    
  3. 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
    
    
    
    
  4. 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
    
    
    
    
  5. 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
    
    
    
    
  6. 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
    
    
    
    
  7. 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)
    
    
  8. 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.
    
  9. 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
    
    
    
    
  10. 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.
    
  11. 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".
    
    
    
    
  12. 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
    
    
    
    
  13. 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
    
    
    
    
  14. 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
    
    
    
    
  15. 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.
    
  16. 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
    
  17. 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
    
    
    
    
  18. 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
    
    
    
    
  19. 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
    
    
    
    
  20. 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
    
    
    
    
  21. 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
    
    
    
    
  22. 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
    
    
    
    
  23. 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
    
    
    
    
  24. 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
    
    
    
    
    
  25. 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
    
    
    
    
  26. 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
    
    
    
    
  27. 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
    
  28. 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
    
    
    
    
  29. 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
    
  30. 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.
    
  31. 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
    
    
    
    
  32. 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
    
    
    
    
  33. 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
    
    
    
    
  34. 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
    
    
    
    
  35. 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
    
    
    
    
  36. 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
    
    
    
    
  37. 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
    
  38. 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
    
    
    
    
  39. 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
    
    
    
    
  40. 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
    
  41. 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
    
    
    
    
  42. 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
    
    
    
    
  43. 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
    
  44. 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
    
    
    
    
  45. 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
    
    
    
    
  46. 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
    
    
    
    
  47. 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
    
  48. 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
    
    
    
    
  49. 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
    
  50. 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
    
    
    
    
  51. 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
    
  52. 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
    
    
    
    
  53. 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