Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hosiO-0002MY-Lb for pgsql-hackers@arkaria.postgresql.org; Sat, 20 Jul 2019 17:00:08 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hosiN-0002bk-GI for pgsql-hackers@arkaria.postgresql.org; Sat, 20 Jul 2019 17:00:07 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hosiN-0002bd-3c for pgsql-hackers@lists.postgresql.org; Sat, 20 Jul 2019 17:00:07 +0000 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hosiJ-0001IR-Jr for pgsql-hackers@lists.postgresql.org; Sat, 20 Jul 2019 17:00:06 +0000 Received: by mail-wm1-x344.google.com with SMTP id a15so31383341wmj.5 for ; Sat, 20 Jul 2019 10:00:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=ZmHKrx4nGnjY4bRep9LjByClxcsQ4eys0Y11tKeYM9Q=; b=oXbwtU/94WIf81VpKTTEjzJujRsXotBXc0LB8A0Pk5Y/E0xtdjof9WlmwgbLld+wFW OTPr/UVZibxKJN6pS+SErs8AFQa+MLNnt52d13OR2Oh4YgaDtH5FHwVApQZAB2RHN5bX oFvN3U0pRIY2pFKMLR/LR+fw+zAjvXQDfIclZNHusPDY4hHsjNuSMi9NN1DjHvmOw1eu KnkaYJ22llUkN6fk8nhtOuBKmaN5QEfWthda/Kp0AhcOmzBhr7X55ikSrENcpWF4e8ek wb4c+Utt9YoopKkCienxtkxufsWjoY42GcDuBu9xdjqLoPm+evzMVxbtrzrLKs3i2lbY 26WQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=ZmHKrx4nGnjY4bRep9LjByClxcsQ4eys0Y11tKeYM9Q=; b=ocd9LT+qbwBRSM2Ls7vZ+bgFRZ5mziCnnK93L6fAZP2CNR2sldogwn2bn28nYuCwCA vIGvDW67E2CEi/EfK+0zLZKAIYpJDZbfpzaTGKfAfKxbkQogZxbV53JcNUhhl2fFuvHe zBSGR/p0p9jay19slbXrTvcMgjC0H9lMdSvPdX7R57+53uzhc0UZKjF4dXSWT5zGV76o jSbT4OX5LS1R5V+Sx1gKsQTROlLduogl875fcs0AbCrCLL2ICF29Wz7+eOqNhFT+iLeE //4MCGQtvy1BWCe67alSKJTGIY3t5gI89KP+kvYKggfQMXUJwz8O+TGLQJE8kan9p1yy 6wtg== X-Gm-Message-State: APjAAAUupl/dEaul7/BrI19f40qyj9Xsk4GKHhQOYTsZbI3C1KkMYVxk zTnv1l5tQ7pU4z7bTdeeNGW7/w== X-Google-Smtp-Source: APXvYqzKTgjRIMPuQf9VI2Ma1oy8hGQ26hLZhub+YQ7L5P4W8oHiBziEXPWDzJ2U/8hGwLZw32t+5g== X-Received: by 2002:a7b:c202:: with SMTP id x2mr52124053wmi.49.1563642000214; Sat, 20 Jul 2019 10:00:00 -0700 (PDT) Received: from localhost ([82.202.112.229]) by smtp.gmail.com with ESMTPSA id c4sm28065165wrt.86.2019.07.20.09.59.55 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Sat, 20 Jul 2019 09:59:55 -0700 (PDT) Date: Sat, 20 Jul 2019 18:59:51 +0200 From: Tomas Vondra To: James Coleman Cc: Peter Geoghegan , Simon Riggs , Rafia Sabih , Shaun Thomas , Dmitry Dolgov <9erthalion6@gmail.com>, Alexander Korotkov , Tom Lane , PostgreSQL Developers Subject: Re: [PATCH] Incremental sort (was: PoC: Partial sort) Message-ID: <20190720165951.m6adwbqi26bsfbjb@development> References: <20190708145853.x2doaqcyj3enol2e@development> <20190709013703.3mbdhsv2gyxtjc42@development> <20190720132244.3vgg2uynfpxh3me5@development> <20190720152512.jpdi2g3notbjcxsd@development> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: User-Agent: NeoMutt/20180716-1444-295967-dirty List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Sat, Jul 20, 2019 at 12:21:01PM -0400, James Coleman wrote: >On Sat, Jul 20, 2019 at 12:12 PM James Coleman wrote: >> >> On Sat, Jul 20, 2019 at 11:25 AM Tomas Vondra >> wrote: >> ... >> > >My current line of investigation is whether we need to do anything in >> > >the parallel portion of create_ordered_paths(). I noticed that the >> > >first-pass patch adding generate_useful_gather_paths() modified that >> > >section but wasn't actually adding any new gather-merge paths (just >> > >bare incremental sort paths). That seems pretty clearly just a >> > >prototype miss, so I modified the prototype to build gather-merge >> > >paths instead (as a side note that change seems to fix an oddity I was >> > >seeing where plans would include a parallel index scan node even >> > >though they weren't parallel plans). While the resulting plan for >> > >something like: >> > > >> > >> > Yes, that seems to be a bug. The block above it clealy has a gather >> > merge nodes, so this one should too. >> > >> > >explain analyze select * from t where t.a in (1,2,3,4,5,6) order by >> > >t.a, t.b limit 50; >> > > >> > >changes cost (to be cheaper) ever so slightly with the gather-merge >> > >addition to create_ordered_paths(), the plan itself is otherwise >> > >identical (including row estimates): >> > > >> > >Limit >> > > -> Gather Merge >> > > -> Incremental Sort >> > > -> Parallel Index Scan >> > > >> > >(Note: I'm forcing parallel plans here with: set >> > >max_parallel_workers_per_gather=4; set min_parallel_table_scan_size=0; >> > >set parallel_tuple_cost=0; set parallel_setup_cost=0; set >> > >min_parallel_index_scan_size=0;) >> > > >> > >I can't seem to come up with a case where adding these gather-merge >> > >paths in create_ordered_paths() isn't entirely duplicative of paths >> > >already created by generate_useful_gather_paths() as called from >> > >apply_scanjoin_target_to_paths() -- which I _think_ makes sense given >> > >that both apply_scanjoin_target_to_paths() and create_ordered_paths() >> > >are called by grouping_planner(). >> > > >> > >Can you think of a case I'm missing here that would make it valuable >> > >to generate new parallel plans in create_ordered_paths()? >> > > >> > >> > Good question. Not sure. I think such path would need to do something on >> > a relation that is neither a join nor a scan - in which case the path >> > should not be created by apply_scanjoin_target_to_paths(). >> > >> > So for example a query like this: >> > >> > SELECT >> > a, b, sum(expensive_function(c)) >> > FROM >> > t >> > GROUP BY a,b >> > ORDER BY a,sum(...) LIMIT 10; >> > >> > should be able to produce a plan like this: >> > >> > -> Limit >> > -> Gather Merge >> > -> Incremental Sort (pathkeys: a, sum) >> > -> Group Aggregate >> > a, b, sum(expensive_function(c)) >> > -> Index Scan (pathkeys: a, b) >> > >> > or something like that, maybe. I haven't tried this, though. The other >> > question is whether such queries are useful in practice ... >> >> Hmm, when I step through on that example input_rel->partial_pathlist >> != NIL is false, so we don't even attempt to consider any extra >> parallel paths in create_ordered_paths(). Nonetheless we get a >> parallel plan, but with a different shape: >> >> Limit >> -> Incremental Sort >> Sort Key: a, (sum(expensive_function(c))) >> Presorted Key: a >> -> Finalize GroupAggregate >> Group Key: a, b >> -> Gather Merge >> Workers Planned: 4 >> -> Partial GroupAggregate >> Group Key: a, b >> -> Sort >> Sort Key: a, b >> -> Parallel Seq Scan on t >> >> (or if I disable seqscan then the sort+seq scan above becomes inc sort >> + index scan) >> >> To be honest, I don't think I understand how you would get a plan like >> that anyway since the index here only has "a" and so can't provide >> (pathkeys: a, b). >> >> Perhaps there's something I'm still missing though. I wasn't stricly adhering to the example we used before, and I imagined there would be an index on (a,b). Sorry if that wasn't clear. > >Also just realized I don't think (?) we can order by the sum inside a >gather-merge -- at least not without having another sort above the >parallel portion? Or is the group aggregate able to also provide >ordering on the final sum after aggregating the partial sums? > Yes, you're right - an extra sort node would be necessary. But I don't think that changes the idea behind that example. The question is whether the extra sorts below the gather would be cheaper than doing a large sort on top of it - but I don't see why wouldn't that be the case, and if we only need a couple of rows from the beginning ... regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services