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 1hbZPO-0006E7-Q1 for pgsql-hackers@arkaria.postgresql.org; Thu, 13 Jun 2019 23:45:31 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hbZPN-0003Ky-CG for pgsql-hackers@arkaria.postgresql.org; Thu, 13 Jun 2019 23:45:29 +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 1hbZPM-0003DS-SU for pgsql-hackers@lists.postgresql.org; Thu, 13 Jun 2019 23:45:29 +0000 Received: from mail-wr1-x430.google.com ([2a00:1450:4864:20::430]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hbZPI-0007zv-PG for pgsql-hackers@postgresql.org; Thu, 13 Jun 2019 23:45:27 +0000 Received: by mail-wr1-x430.google.com with SMTP id v14so563661wrr.4 for ; Thu, 13 Jun 2019 16:45:24 -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=FhCd/tE8WRh38VzdFS+FReqilYS2yVHm1oTuPqfBDew=; b=lTTCDtVGEDCcqbqRNn48K7AZXdcOvYTiMQeJoOXBgy/LwfawfmZmpvAguvyuhN5EKZ ItqSdpcIjq3GrJuqJvj5xv8+Y4Kua3ZxOECrteGuQnbluV5tAHdYyGnJ54IOqmR/2ypi 0m5o/fF/CwAEiOwMTX8PAbRkyY3Wg2SdXf3LV5O42Oo+2xElIFoZYgVxIBrOwBGRWj+u gcl+ChbV5zItMzUgldFQtPcfang+J05lfOFc8em2qSuPaZxkI5oQpxPJTi9pV0DxGHte Gr983aHdJjMpXeoWeCZ5SRiThZKlgrephNifENRdJv/g2rl4MeEcUpKalLhBqkJ00qEB KQSA== 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=FhCd/tE8WRh38VzdFS+FReqilYS2yVHm1oTuPqfBDew=; b=shuN4oGON56CT8xz72YhEWIWmx4gvLgQTKL5v5FGIa0SXDd1f1O4Ct66IGyAxiczQr +oB/BohXD9ykOqynDE46CTGMVYzag6nA2b3/qGiR1JfX0h33fWAKJ0yT4TZ3xDQzm8w5 XlNxDkyn/cUNiiPL2HPBrL1cBCViFWq4DKqOeGCp85tNlXMiA5U0saMzjHzejH4Jgvqx AzAJKP91g2IIk35fzXdj4sny+dzV30hrGVqZDs8mqg1s50ofXoUVn/GG2ijgmq1tWni3 Wdk1Bo7Ir39aaDHnBNNo5kwN1FA2wL/iwDJ2v28awNgrgygEBiqiXcE2xGL+Ha/tiDLh pfbg== X-Gm-Message-State: APjAAAWjZ4lJNGdELlh9DgppYcu8x/t4u/6+PJb8CDk6Jy57/qRDqXhU EzRmSCT/RGo5pUl6SGBThF+6qw== X-Google-Smtp-Source: APXvYqzVKEHBDdu0ScCbq6l+83Kt98CiS1Vo9xhpSIr7pczENMniAAZV8XGiKwFoLgNLsHULTIM8WA== X-Received: by 2002:adf:eb4e:: with SMTP id u14mr14592877wrn.168.1560469521846; Thu, 13 Jun 2019 16:45:21 -0700 (PDT) Received: from localhost (ip-86-49-243-43.net.upcbroadband.cz. [86.49.243.43]) by smtp.gmail.com with ESMTPSA id d17sm1894042wrx.9.2019.06.13.16.45.20 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 13 Jun 2019 16:45:20 -0700 (PDT) Date: Fri, 14 Jun 2019 01:45:18 +0200 From: Tomas Vondra To: Richard Guo Cc: PostgreSQL-development Subject: Re: Parallel grouping sets Message-ID: <20190613234518.a3votby32snkwiju@development> References: 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 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Wed, Jun 12, 2019 at 10:58:44AM +0800, Richard Guo wrote: >Hi all, > >Paul and I have been hacking recently to implement parallel grouping >sets, and here we have two implementations. > >Implementation 1 >================ > >Attached is the patch and also there is a github branch [1] for this >work. > >Parallel aggregation has already been supported in PostgreSQL and it is >implemented by aggregating in two stages. First, each worker performs an >aggregation step, producing a partial result for each group of which >that process is aware. Second, the partial results are transferred to >the leader via the Gather node. Finally, the leader merges the partial >results and produces the final result for each group. > >We are implementing parallel grouping sets in the same way. The only >difference is that in the final stage, the leader performs a grouping >sets aggregation, rather than a normal aggregation. > >The plan looks like: > ># explain (costs off, verbose) select c1, c2, avg(c3) from t2 group by >grouping sets((c1,c2), (c1), (c2,c3)); > QUERY PLAN >--------------------------------------------------------- > Finalize MixedAggregate > Output: c1, c2, avg(c3), c3 > Hash Key: t2.c2, t2.c3 > Group Key: t2.c1, t2.c2 > Group Key: t2.c1 > -> Gather Merge > Output: c1, c2, c3, (PARTIAL avg(c3)) > Workers Planned: 2 > -> Sort > Output: c1, c2, c3, (PARTIAL avg(c3)) > Sort Key: t2.c1, t2.c2 > -> Partial HashAggregate > Output: c1, c2, c3, PARTIAL avg(c3) > Group Key: t2.c1, t2.c2, t2.c3 > -> Parallel Seq Scan on public.t2 > Output: c1, c2, c3 >(16 rows) > >As the partial aggregation can be performed in parallel, we can expect a >speedup if the number of groups seen by the Finalize Aggregate node is >some less than the number of input rows. > >For example, for the table provided in the test case within the patch, >running the above query in my Linux box: > ># explain analyze select c1, c2, avg(c3) from t2 group by grouping >sets((c1,c2), (c1), (c2,c3)); -- without patch > Planning Time: 0.123 ms > Execution Time: 9459.362 ms > ># explain analyze select c1, c2, avg(c3) from t2 group by grouping >sets((c1,c2), (c1), (c2,c3)); -- with patch > Planning Time: 0.204 ms > Execution Time: 1077.654 ms > Very nice. That's pretty much exactly how I imagined it'd work. >But sometimes we may not benefit from this patch. For example, in the >worst-case scenario the number of groups seen by the Finalize Aggregate >node could be as many as the number of input rows which were seen by all >worker processes in the Partial Aggregate stage. This is prone to >happening with this patch, because the group key for Partial Aggregate >is all the columns involved in the grouping sets, such as in the above >query, it is (c1, c2, c3). > >So, we have been working on another way to implement parallel grouping >sets. > >Implementation 2 >================ > >This work can be found in github branch [2]. As it contains some hacky >codes and a list of TODO items, this is far from a patch. So please >consider it as a PoC. > >The idea is instead of performing grouping sets aggregation in Finalize >Aggregate, we perform it in Partial Aggregate. > >The plan looks like: > ># explain (costs off, verbose) select c1, c2, avg(c3) from t2 group by >grouping sets((c1,c2), (c1)); > QUERY PLAN >-------------------------------------------------------------- > Finalize GroupAggregate > Output: c1, c2, avg(c3), (gset_id) > Group Key: t2.c1, t2.c2, (gset_id) > -> Gather Merge > Output: c1, c2, (gset_id), (PARTIAL avg(c3)) > Workers Planned: 2 > -> Sort > Output: c1, c2, (gset_id), (PARTIAL avg(c3)) > Sort Key: t2.c1, t2.c2, (gset_id) > -> Partial HashAggregate > Output: c1, c2, gset_id, PARTIAL avg(c3) > Hash Key: t2.c1, t2.c2 > Hash Key: t2.c1 > -> Parallel Seq Scan on public.t2 > Output: c1, c2, c3 >(15 rows) > OK, I'm not sure I understand the point of this - can you give an example which is supposed to benefit from this? Where does the speedup came from? regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services