Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jJptc-0005DZ-SF for pgsql-hackers@arkaria.postgresql.org; Thu, 02 Apr 2020 02:47:57 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1jJptb-0003nW-Os for pgsql-hackers@arkaria.postgresql.org; Thu, 02 Apr 2020 02:47:55 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jJptb-0003nP-9c for pgsql-hackers@lists.postgresql.org; Thu, 02 Apr 2020 02:47:55 +0000 Received: from mail-wr1-x443.google.com ([2a00:1450:4864:20::443]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jJptY-0002ti-K7 for pgsql-hackers@lists.postgresql.org; Thu, 02 Apr 2020 02:47:54 +0000 Received: by mail-wr1-x443.google.com with SMTP id p10so2395872wrt.6 for ; Wed, 01 Apr 2020 19:47:52 -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; bh=UQvq8gtZW01j2sgJjawcBsPUcRl1pfR2HWkdtH5xqaQ=; b=m008CNDfbbnz+5+cLPLmcf/rkm/JxQA3R1LdoKtNwBT5MYVyvGIMFZRof7KbuBIkZt +BwrnqPf8h7jBiuKbnBaiLcOODqlu7Wd3suGqrQw5rtKEQ/4I+8E24xfg+2CvDcjupJO FBiuD27bDhEzzNRqAznnIugROLY3k+yIBI3GnjEEjngFtD99eKYVSZgQFeRqZp0r59S9 j7YHr0XWDZQuR/LWv/pTfmxn+QgnvwsRoyz+E7qZC910M35r11dyiJl+cXfZo0kqW+Rz Xfi8Dx3bW4ryZkCqsBC3Pg8RT6zvV3lLaeP+IcnnSq0nyE7Hobflxomc5PgR4FZtzXRM bagw== 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; bh=UQvq8gtZW01j2sgJjawcBsPUcRl1pfR2HWkdtH5xqaQ=; b=WcQLPEP996YvVCdsya8MZ1zVylg4KslzlztFmGQq0Yk6dAMgjx4lfSog2+NSzzdxgh gEI7RDjvHglp9f+GLmrfkOnHXdky4vhoP0xosJqXqDVvb0x5igulSWdMrWrjnqzr8j93 BmMAuonSIwYFwVSflpCNG7Uzeq3ChDSMICgmD8AWtrFJs7ixCCBG5ajcQwVt7aV5hlHz 1mCZjflMkU1DDdya6FUucyzRcq2kJbgHwTxqB5mYf2fj6egxykUMt4Oc4HohrmPPv5uA VPbWuVejZ8gor8V8xx9iwMhBQ1kno2RggfyZSniAbFpZi4zkzH1HuH3DFHiI4lrBP12j ao8g== X-Gm-Message-State: AGi0Pua5qDGPrnwrW1lGKGIjPJgXgXs35Ux+/ec1YtYMgCbC7606+cwU YNVMNyVuAwgB6ezEdBj/odZUfA== X-Google-Smtp-Source: APiQypLIuf4mKhAC7oeFOP2bVXhBxCxGzt2+c3vCxg8EvM+HF4fnot9mEF77v6ttos5yWsnxpUAC6Q== X-Received: by 2002:adf:ecc3:: with SMTP id s3mr1012214wro.32.1585795671049; Wed, 01 Apr 2020 19:47:51 -0700 (PDT) Received: from localhost (ip-86-49-253-141.net.upcbroadband.cz. [86.49.253.141]) by smtp.gmail.com with ESMTPSA id j11sm5074701wmi.33.2020.04.01.19.47.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Apr 2020 19:47:50 -0700 (PDT) Date: Thu, 2 Apr 2020 04:47:46 +0200 From: Tomas Vondra To: James Coleman Cc: Tom Lane , Alvaro Herrera , Michael Paquier , Rafia Sabih , Peter Geoghegan , Simon Riggs , Shaun Thomas , Dmitry Dolgov <9erthalion6@gmail.com>, Alexander Korotkov , PostgreSQL Developers , Andreas Karlsson Subject: Re: [PATCH] Incremental sort (was: PoC: Partial sort) Message-ID: <20200402024746.5wlwk6q7eiv5faux@development> References: <20200401003809.pup7i7yr6pwramk3@development> <20200401015925.bmbbqc3ple5rf3yn@development> <20200401024424.g4uuerdvxqohvzks@development> <20200401214215.ut6b72e3zlbm33w2@development> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Wed, Apr 01, 2020 at 10:09:20PM -0400, James Coleman wrote: >On Wed, Apr 1, 2020 at 5:42 PM Tomas Vondra > wrote: >> ... >> I've realized the way get_useful_pathkeys_for_relation() is coded kinda >> works against the fastpath we added when comparing pathkeys. That >> depends on comparing pointers to the list, but we've been building new >> lists (and then returned those) which defeats the optimization. Attached >> is a patch that returns the original list in most cases (and only >> creates a copy when really necessary). This might also save a few cycles >> on bulding the new list, of course. >> >> I've done a bunch of read-only pgbench tests with fairly small scales (1 >> and 10). First with the built-in read-only transaction, and also with a >> simple custom query doing an order-by. And I did this both on the >> default schema and with a bunch of extra indexes. The script I used to >> run this is attached, along with a summary of results. >> >> There are results for master and v40 and v50 patches (the v50 also >> includes the extra patch fixing get_useful_pathkeys_for_relation). >> >> Overall, I'm happy with those results - the v50 seems to be within 1% of >> master, in both directions. This very much seems like a noise. >> >> I still want to do a bit more review of the costing / tuplesort changes, >> which I plan to do tomorrow. If that goes well, I plan to start >> committing this. So please if you think this is not ready or wants more > >I think we need to either implement this or remove the comment: >* XXX I wonder if we need to consider adding a projection here, as >* create_ordered_paths does. >in generate_useful_gather_paths(). > Yeah. I think we don't need the projection here. My reasoning is that if we don't need it in generate_gather_paths(), we don't need it here. >In the same function we have the following code: >/* > * When the partial path is already sorted, we can just add a gather > * merge on top, and we're done - no point in adding explicit sort. > * > * XXX Can't we skip this (maybe only for the cheapest partial path) > * when the path is already sorted? Then it's likely duplicate with > * the path created by generate_gather_paths. > */ >if (is_sorted) >{ > path = create_gather_merge_path(root, rel, subpath, rel->reltarget, > > subpath->pathkeys, NULL, rowsp); > > add_path(rel, &path->path); > continue; >} > >looking at the relevant loop in generate_gather_paths: >/* > * For each useful ordering, we can consider an order-preserving Gather > * Merge. > */ >foreach(lc, rel->partial_pathlist) >{ > Path *subpath = (Path *) lfirst(lc); > GatherMergePath *path; > > if (subpath->pathkeys == NIL) > continue; > > rows = subpath->rows * subpath->parallel_workers; > path = create_gather_merge_path(root, rel, subpath, rel->reltarget, > > subpath->pathkeys, NULL, rowsp); > add_path(rel, &path->path); >} > >I believe we can eliminate the block entirely in >generate_useful_gather_paths(). Here's my reasoning: all paths for >which is_sorted is true must necessarily have pathkeys, and since we >already add a gather merge for every subpath with pathkeys, we've >already added gather merge paths for all of these. > >I've included a patch to change this, but let me know if the reasoning >isn't sound. > Good catch! I think you're correct - we don't need to generate this path, and we can just skip that partial path entirely. >We can also remove the XXX on this comment (in the same function): >* XXX This is not redundant with the gather merge path created in >* generate_gather_paths, because that merely preserves ordering of >* the cheapest partial path, while here we add an explicit sort to >* get match the useful ordering. > >because of this code in generate_gather_paths(): >cheapest_partial_path = linitial(rel->partial_pathlist); >rows = > cheapest_partial_path->rows * cheapest_partial_path->parallel_workers; >simple_gather_path = (Path *) > create_gather_path(root, rel, cheapest_partial_path, rel->reltarget, > NULL, rowsp); >add_path(rel, simple_gather_path); > >but we can cleanup the comment a bit: fix the grammar issue in the >last line and fix the reference to gather merge path (it's a gather >path). > >I've included that in the same patch. > OK, makes sense. >I also noticed that in create_incremental_sort_path we have this: >/* XXX comparison_cost shouldn't be 0? */ >but I guess that's part of what you're reviewing tomorrow. > Right, one of the bits. >> time for a review, let me know. I'm not yet sure if I'll commit this as >> a single change, or in three separate commits. > >I don't love the idea of committing it as a single patch, but at least >the first two I think probably go together. Otherwise we're >introducing a "fix" with no proven impact that will slow down planning >(even if only in a small way) only to intend to condition that on a >GUC in the next commit. > >But I think you could potentially make an argument for keeping the >additional paths separate...but it's not absolutely necessary IMO. > OK. I've been actually wondering whether to move the add_partial_path after the main patch, for exactly this reason. >> James, can you review the proposed extra fix and merge the fixes into >> the main patches? > >I've reviewed it, and it looks correct, so merged into the main series. > >Summary: >The attached series includes a couple of XXX fixes or comment cleanup >as noted above. I believe there are two more XXXs that needs to be >answered before we merge ("do we need to consider adding a projection" >and "what is the comparison cost for incremental sort"). > Thanks! regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services