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 1hlcKY-0000Ma-SD for pgsql-hackers@arkaria.postgresql.org; Thu, 11 Jul 2019 16:54:03 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hlcKX-0008Dy-EH for pgsql-hackers@arkaria.postgresql.org; Thu, 11 Jul 2019 16:54:01 +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 1hlcKX-0008Dr-5S for pgsql-hackers@lists.postgresql.org; Thu, 11 Jul 2019 16:54:01 +0000 Received: from mail-qt1-f194.google.com ([209.85.160.194]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hlcKU-0003G0-7q for pgsql-hackers@postgresql.org; Thu, 11 Jul 2019 16:54:00 +0000 Received: by mail-qt1-f194.google.com with SMTP id h18so4986072qtm.9 for ; Thu, 11 Jul 2019 09:53:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:reply-to:subject:to:cc:references:from :organization:message-id:date:user-agent:mime-version:in-reply-to :content-language:content-transfer-encoding; bh=+VVhm0/9i0Ix9qB7M574Crlh4UpokTy6iSjSRKyR8CM=; b=DEHjTml3yRR471MvHR50gbG/LogBSNycb8UU+XWtt8dHVfLEwSS05kGowdQ5ZKCT42 JReL5dzmHDbtaGSF39xOcQbBhCV3CD6O8bFriewBKrKlDK6WAuzhV1KPELlPpIh9HQmB oBRE2XtBn7sDrCLNO9NaqjILZ6qgb1iXvtlCIuT6gE4z6QBziqFIMwQ5Bt/tp5M+7VCe BVjL+4gd5hlSGCs2bnYFesirDCgtAGr5VRA/dJMxwQZfboHortDIyvrRxHQ9uOSQg58x 98x1Ze98raR8Q/9hWSNveWfW95Yt9mMody8DmOQc9DN62TohQl0oMpKFzTCb00NJv+Qs WabQ== X-Gm-Message-State: APjAAAUPZtW3XmqaHnOLMeenX5ztvPRqMgL97HEotNTmnCai62f5YCdf B59otwIOb2tnjI6riEAW0X5iiw== X-Google-Smtp-Source: APXvYqwm6nJEjUKR7owFkYUaX1OnSE7UIbMVtUIJfQxLwYE80r1N63vnkgZuwToDe3cojjforfQUOw== X-Received: by 2002:ac8:6747:: with SMTP id n7mr2603482qtp.19.1562864036272; Thu, 11 Jul 2019 09:53:56 -0700 (PDT) Received: from localhost.localdomain (c-24-61-8-151.hsd1.ma.comcast.net. [24.61.8.151]) by smtp.gmail.com with ESMTPSA id a21sm2256256qka.113.2019.07.11.09.53.54 (version=TLS1_3 cipher=AEAD-AES128-GCM-SHA256 bits=128/128); Thu, 11 Jul 2019 09:53:55 -0700 (PDT) Reply-To: jesper.pedersen@redhat.com Subject: Re: Index Skip Scan To: David Rowley Cc: Dmitry Dolgov <9erthalion6@gmail.com>, Floris Van Nee , Thomas Munro , James Coleman , Rafia Sabih , Jeff Janes , Peter Geoghegan , Tomas Vondra , Thomas Munro , Bhushan Uparkar , PostgreSQL-development , Alexander Korotkov References: <2685f020-f302-9bf6-1b5c-ebc2bcebc635@2ndquadrant.com> <1559763453006.85615@Optiver.com> <1559763570329.85227@Optiver.com> <4d469bf2-49ff-bc3d-a428-6c7b5d87d526@redhat.com> <1562769595280.16860@Optiver.com> From: Jesper Pedersen Organization: Red Hat Message-ID: <994cbf82-333c-56d7-2860-9c8c85aba790@redhat.com> Date: Thu, 11 Jul 2019 12:53:54 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.2 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi David, On 7/11/19 7:38 AM, David Rowley wrote: > The UniqueKeys idea is quite separate from pathkeys. Currently, a > Path can have a List of PathKeys which define the order that the > tuples will be read from the Plan node that's created from that Path. > The idea with UniqueKeys is that a Path can also have a non-empty List > of UniqueKeys to define that there will be no more than 1 row with the > same value for the Paths UniqueKey column/exprs. > > As of now, if you look at standard_qp_callback() sets > root->query_pathkeys, the idea here would be that the callback would > also set a new List field named "query_uniquekeys" based on the > group_pathkeys when non-empty and !root->query->hasAggs, or by using > the distinct clause if it's non-empty. Then in build_index_paths() > around the call to match_pathkeys_to_index() we'll probably also want > to check if the index can support UniqueKeys that would suit the > query_uniquekeys that were set during standard_qp_callback(). > > As for setting query_uniquekeys in standard_qp_callback(), this should > be simply a matter of looping over either group_pathkeys or > distinct_pathkeys and grabbing the pk_eclass from each key and making > a canonical UniqueKey from that. To have these canonical you'll need > to have a new field in PlannerInfo named canon_uniquekeys which will > do for UniqueKeys what canon_pathkeys does for PathKeys. So you'll > need an equivalent of make_canonical_pathkey() in uniquekey.c > > With this implementation, the code that the patch adds in > create_distinct_paths() can mostly disappear. You'd only need to look > for a path that uniquekeys_contained_in() matches the > root->query_uniquekeys and then just leave it to > set_cheapest(distinct_rel); to pick the cheapest path. > > It would be wasted effort to create paths with UniqueKeys if there's > multiple non-dead base rels in the query as the final rel in > create_distinct_paths would be a join rel, so it might be worth > checking that before creating such index paths in build_index_paths(). > However, down the line, we could carry the uniquekeys forward into the > join paths if the join does not duplicate rows from the other side of > the join... That's future stuff though, not for this patch, I don't > think. > > I think a UniqueKey can just be a struct similar to PathKey, e.g be > located in pathnodes.h around where PathKey is defined. Likely we'll > need a uniquekeys.c file that has the equivalent to > pathkeys_contained_in() ... uniquekeys_contained_in(), which return > true if arg1 is a superset of arg2 rather than check for one set being > a prefix of another. As you mention above: UniqueKeys { x, y } == > UniqueKeys { y, x }. That superset check could perhaps be optimized > by sorting UniqueKey lists in memory address order, that'll save > having a nested loop, but likely that's not going to be required for a > first cut version. This would work since you'd want UniqueKeys to be > canonical the same as PathKeys are (Notice that compare_pathkeys() > only checks memory addresses of pathkeys and not equals()). > > I think the UniqueKey struct would only need to contain an > EquivalenceClass field. I think all the other stuff that's in PathKey > is irrelevant to UniqueKey. > Thanks for the feedback ! I'll work on these changes for the next uniquekey patch. Best regards, Jesper