Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sUQZo-002yEM-MB for pgsql-hackers@arkaria.postgresql.org; Thu, 18 Jul 2024 12:49:40 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1sUQZm-00FtuZ-IE for pgsql-hackers@arkaria.postgresql.org; Thu, 18 Jul 2024 12:49:38 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sUQZm-00FtuR-5v for pgsql-hackers@lists.postgresql.org; Thu, 18 Jul 2024 12:49:38 +0000 Received: from mail-lj1-x22c.google.com ([2a00:1450:4864:20::22c]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1sUQZf-000CVB-5o for pgsql-hackers@lists.postgresql.org; Thu, 18 Jul 2024 12:49:38 +0000 Received: by mail-lj1-x22c.google.com with SMTP id 38308e7fff4ca-2eedea0fd88so10090771fa.2 for ; Thu, 18 Jul 2024 05:49:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721306969; x=1721911769; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=HVk2jM0Qlp6SR0LrtzS/dy+mAjYeN990wZs8PGQTHGU=; b=Q+arR6vG6dxDwnFTuU77yWUGgA9qtA5SAki77imHx6/e1QEEuKUIBjR4SX0Rdmnvu0 vWIhR/j5mdfhOKiYOJewr1ubmgCuleCL+pBSxsVJMHYdtojzf2d5VwpSl75dHjpvKG1H cwt66gVFcU4ky+ziPZy0DhqOUu0inUrujJ2e154ebQtEOMBTC8KVlq8rjSVYLZ2/1jfp RGx7t5ifwGDvMmwISpDNtoqENchr7HtSRfor/uSsiQpiZ2TUc1Mg0h5xDGVrCF3RhRXj TWuisbfkZ85P38G+dgf0UVMg9TbAdG1uontOS0FW+VX/6IV4T49VWOoQauePBN4q+HPZ Ltjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721306969; x=1721911769; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=HVk2jM0Qlp6SR0LrtzS/dy+mAjYeN990wZs8PGQTHGU=; b=qS2oZufDb4w1kaD1nHcKXIEIOyrQFLmU2Y6fs5gdw7r190ieiFeULyofqDYZfQDwyJ j6XRZla2S0ipOUJGjii/t4WPX92kSh6OyUyq15kbG0VNLCoz59ER+cYWFw+VNTtbflyd 6ZNXRYBnh51OjFu/ZPyQcoJ+Uh1G/B88dSjrVUR0ns4JEdZWh55Sn1CGsad8tqUhCEpW 2a9dq3Q1ZkHOi+2u0pOU/qJgIHxD7Qmv9OgIB9lM1ohp4I/Q9xVq8uyfXGxBVPri/UVr wWsCXmQUIQduuepkEr7l+/osXZqsKTIyFztXVKuKZtXyrr1X7arFH7Rffw3EjtGbFYwq uSPA== X-Gm-Message-State: AOJu0Yz34yBUUyMj5KIjyWz6NXHgWPf6mYwBFvm1fV+H25cGJx8Qo6F3 N9Y2Dbz9BIJS7oSxspX1So9xJYKJUTCqyt4imv+93/ZYB7+L4IzlfX4XUUhJk6XpzE9+QmvMpth 5RqcE619DSmcRPloHaXtjTekrkOg= X-Google-Smtp-Source: AGHT+IFfg71I/UtwSals+0CpoXGhFH4DxmmNZrotBZtMzJtP6CNObx8pZsyc/kqnQGchVdV5MSmZYurvC+Wc8lsSqwM= X-Received: by 2002:a2e:9c07:0:b0:2eb:68d0:88be with SMTP id 38308e7fff4ca-2ef05c78f5dmr16844761fa.12.1721306968903; Thu, 18 Jul 2024 05:49:28 -0700 (PDT) MIME-Version: 1.0 References: <24c11397-d9a1-4aac-a999-a79352a6a35b@gmail.com> <86490ec1-ac42-4169-b0fc-cc7116a4ca25@gmail.com> In-Reply-To: <86490ec1-ac42-4169-b0fc-cc7116a4ca25@gmail.com> From: Matthias van de Meent Date: Thu, 18 Jul 2024 14:49:15 +0200 Message-ID: Subject: Re: Expand applicability of aggregate's sortop optimization To: Andrei Lepikhov Cc: PostgreSQL Hackers , David Rowley , ilmari@ilmari.org Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, 17 Jul 2024 at 16:09, Andrei Lepikhov wrote: > > On 17/7/2024 16:33, Matthias van de Meent wrote: > > On Wed, 17 Jul 2024 at 05:29, Andrei Lepikhov wrote: > >> Thanks for the job! I guess you could be more brave and push down also > >> FILTER statement. > > > > While probably not impossible, I wasn't planning on changing this code > > with new optimizations; just expanding the applicability of the > > current optimizations. > Got it>> As I see, the code: > >> aggsortop = fetch_agg_sort_op(aggref->aggfnoid); > >> if (!OidIsValid(aggsortop)) > >> return false; /* not a MIN/MAX aggregate */ > >> > >> used twice and can be evaluated earlier to avoid duplicated code. > > > > The code is structured like this to make sure we only start accessing > > catalogs once we know that all other reasons to bail out from this > > optimization indicate we can apply the opimization. You'll notice that > > I've tried to put the cheapest checks that only use caller-supplied > > information first, and catalog accesses only after that. > > > > If the fetch_agg_sort_op clause would be deduplicated, it would either > > increase code complexity to handle both aggref->aggorder paths, or it > > would increase the cost of planning MAX(a ORDER BY b) because of the > > newly added catalog access. > IMO it looks like a micro optimisation. But I agree, it is more about > code style - let the committer decide what is better.>> Also, I'm unsure > about the necessity of looking through the btree > >> classes. Maybe just to check the commutator to the sortop, like in the > >> diff attached? Or could you provide an example to support your approach? > > > > I think it could work, but I'd be hesitant to rely on that, as > > commutator registration is optional (useful, but never required for > > btree operator classes' operators). Looking at the btree operator > > class, which is the definition of sortability in PostgreSQL, seems > > more suitable and correct. > Hm, I dubious about that. Can you provide an example which my variant > will not pass but your does that correctly? Here is one: """ CREATE OPERATOR @@> ( function=int4gt, leftarg=int4, rightarg=int4 ); CREATE OPERATOR @@>= ( function=int4ge, leftarg=int4, rightarg=int4 ); CREATE OPERATOR @@= ( function=int4eq, leftarg=int4, rightarg=int4 ); CREATE OPERATOR @@<= ( function=int4le, leftarg=int4, rightarg=int4 ); CREATE OPERATOR @@< ( function=int4lt, leftarg=int4, rightarg=int4 ); CREATE OPERATOR CLASS my_int_ops FOR TYPE int USING btree AS OPERATOR 1 @<@, OPERATOR 2 @<=@, OPERATOR 3 @=@, OPERATOR 4 @>=@, OPERATOR 5 @>@, FUNCTION 1 btint4cmp; CREATE AGGREGATE my_int_max ( BASETYPE = int4, SFUNC = int4larger, STYPE = int4, SORTOP = @>@ ); CREATE TABLE my_table AS SELECT id::int4 FROM generate_series(1, 10000) id; CREATE INDEX ON my_table (id my_int_ops); SELECT my_int_max(id ORDER BY id USING @<@ ) from my_table; """ Because the @<@ and @>@ operators are not registered as commutative, it couldn't apply the optimization in your patch, while the btree operator check does allow it to apply the optimization. Aside: Arguably, checking for commutator operators would not be incorrect when looking at it from "applied operators" point of view, but if that commutative operator isn't registered as opposite ordering of the same btree opclass, then we'd probably break some assumptions of some aggregate's sortop - it could be registered with another opclass, and that could cause us to select a different btree opclass (thus: ordering) than is indicated to be required by the aggregate; the thing we're trying to protect against here. Kind regards, Matthias van de Meent Neon (https://neon.tech)