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 1hij6Y-0000gC-0V for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Jul 2019 17:31:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hij6U-0007rA-Rp for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Jul 2019 17:31:34 +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 1hij6U-0007r3-J5 for pgsql-hackers@lists.postgresql.org; Wed, 03 Jul 2019 17:31:34 +0000 Received: from mail-qt1-f195.google.com ([209.85.160.195]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hij6M-0000MX-8d for pgsql-hackers@postgresql.org; Wed, 03 Jul 2019 17:31:33 +0000 Received: by mail-qt1-f195.google.com with SMTP id 44so750985qtg.11 for ; Wed, 03 Jul 2019 10:31:25 -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=oTRLN+dn+o095S9KJvCti6hsZoY3Ta7+n5DjoacmZVI=; b=Qe4RiUfM3tK4sZdBZp6ZsZEHNqGuFsSDdB0BffT4rAMHVqWjUDtAZuPtvh5KlgHLDx Vtp2BOLJo7ugOGVSl0ErHpjE2mb8PfL6MLoHJQJBgj+DkDrt8YBMvRn/1VCiGdTo3ty4 hjJ+15TzCIKyuWh0yP4njV7JOUa2gf5+/DlNies/slDrTmMV6kpWKB/T7fIi1Tfy3Uzi Qul9hcnFSrEhGGyyfNeeM/PgDpg47FPMsWImix2kkpCsU2WeUWjs0SHckxklwhABlXhj Iq4IYv98i9jzj0hvXQx/AERXhdxYrGo7WiiGUZXjGHqsFfAiK5JfacrwpC5EHavO9cI0 BijA== X-Gm-Message-State: APjAAAWoxy7eBxFQVX+L0vSIAmo+Z6+0gxaL1CElV4GQgpr0yH1BCUVE Ah6XcMXGZAYYGGtVjDCSFVTAAg== X-Google-Smtp-Source: APXvYqy7/jTJPWed5QDJAI9anYzILKeg/vW19P9wbrQKkwANSrWGhFDcSRmc9CAMGyYt5t56Vy1ySA== X-Received: by 2002:ac8:5298:: with SMTP id s24mr31868261qtn.303.1562175084187; Wed, 03 Jul 2019 10:31:24 -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 f19sm1197508qtq.5.2019.07.03.10.31.22 (version=TLS1_3 cipher=AEAD-AES128-GCM-SHA256 bits=128/128); Wed, 03 Jul 2019 10:31:23 -0700 (PDT) Reply-To: jesper.pedersen@redhat.com Subject: Re: Index Skip Scan To: David Rowley , Thomas Munro Cc: Dmitry Dolgov <9erthalion6@gmail.com>, Floris Van Nee , 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> <1559361698401.22864@Optiver.com> <1559362223126.18661@Optiver.com> <988b7763-5c55-1be1-b7b6-f3a68eff0d40@redhat.com> <1559763453006.85615@Optiver.com> <1559763570329.85227@Optiver.com> <4d469bf2-49ff-bc3d-a428-6c7b5d87d526@redhat.com> From: Jesper Pedersen Organization: Red Hat Message-ID: <9f4ef571-2f9e-2f5f-e2e3-c1632f3a3d7b@redhat.com> Date: Wed, 3 Jul 2019 13:31:21 -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 Thomas and David, Thanks for the feedback ! On 7/2/19 8:27 AM, David Rowley wrote: > On Tue, 2 Jul 2019 at 21:00, Thomas Munro wrote: >> I took this for a quick spin today. The DISTINCT ON support is nice >> and I think it will be very useful. I've signed up to review it and >> will have more to say later. But today I had a couple of thoughts >> after looking into how src/backend/optimizer/plan/planagg.c works and >> wondering how to do some more skipping tricks with the existing >> machinery. >> >> 1. SELECT COUNT(DISTINCT i) FROM t could benefit from this. (Or >> AVG(DISTINCT ...) or any other aggregate). Right now you get a seq >> scan, with the sort/unique logic inside the Aggregate node. If you >> write SELECT COUNT(*) FROM (SELECT DISTINCT i FROM t) ss then you get >> a skip scan that is much faster in good cases. I suppose you could >> have a process_distinct_aggregates() in planagg.c that recognises >> queries of the right form and generates extra paths a bit like >> build_minmax_path() does. I think it's probably better to consider >> that in the grouping planner proper instead. I'm not sure. > > I think to make that happen we'd need to do a bit of an overhaul in > nodeAgg.c to allow it to make use of presorted results instead of > having the code blindly sort rows for each aggregate that has a > DISTINCT or ORDER BY. The planner would also then need to start > requesting paths with pathkeys that suit the aggregate and also > probably dictate the order the AggRefs should be evaluated to allow > all AggRefs to be evaluated that can be for each sort order. Once > that part is done then the aggregates could then also request paths > with certain "UniqueKeys" (a feature I mentioned in [1]), however we'd > need to be pretty careful with that one since there may be other parts > of the query that require that all rows are fed in, not just 1 row per > value of "i", e.g SELECT COUNT(DISTINCT i) FROM t WHERE z > 0; can't > just feed through 1 row for each "i" value, since we need only the > ones that have "z > 0". Getting the first part of this solved is much > more important than making skip scans work here, I'd say. I think we > need to be able to walk before we can run with DISTINCT / ORDER BY > aggs. > I agree that the above is outside of scope for the first patch -- I think the goal should be the simple use-cases for IndexScan and IndexOnlyScan. Maybe we should expand [1] with possible cases, so we don't lose track of the ideas. >> 2. SELECT i, MIN(j) FROM t GROUP BY i could benefit from this if >> you're allowed to go forwards. Same for SELECT i, MAX(j) FROM t GROUP >> BY i if you're allowed to go backwards. Those queries are equivalent >> to SELECT DISTINCT ON (i) i, j FROM t ORDER BY i [DESC], j [DESC] >> (though as Floris noted, the backwards version gives the wrong answers >> with v20). That does seem like a much more specific thing applicable >> only to MIN and MAX, and I think preprocess_minmax_aggregates() could >> be taught to handle that sort of query, building an index only scan >> path with skip scan in build_minmax_path(). > > For the MIN query you just need a path with Pathkeys: { i ASC, j ASC > }, UniqueKeys: { i, j }, doing the MAX query you just need j DESC. > Ok. > The more I think about these UniqueKeys, the more I think they need to > be a separate concept to PathKeys. For example, UniqueKeys: { x, y } > should be equivalent to { y, x }, but with PathKeys, that's not the > case, since the order of each key matters. UniqueKeys equivalent > version of pathkeys_contained_in() would not care about the order of > individual keys, it would say things like, { a, b, c } is contained in > { b, a }, since if the path is unique on columns { b, a } then it must > also be unique on { a, b, c }. > I'm looking at this, and will keep this in mind. Thanks ! [1] https://wiki.postgresql.org/wiki/Loose_indexscan Best regards, Jesper