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 1sjPIg-000RMb-Hr for pgsql-hackers@arkaria.postgresql.org; Wed, 28 Aug 2024 20:29:54 +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 1sjPIe-00AEna-JM for pgsql-hackers@arkaria.postgresql.org; Wed, 28 Aug 2024 20:29:53 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sjPIe-00AEnS-6o for pgsql-hackers@lists.postgresql.org; Wed, 28 Aug 2024 20:29:52 +0000 Received: from mail-pf1-x434.google.com ([2607:f8b0:4864:20::434]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1sjPIY-001tlA-7V for pgsql-hackers@postgresql.org; Wed, 28 Aug 2024 20:29:51 +0000 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-71423704ef3so5714540b3a.3 for ; Wed, 28 Aug 2024 13:29:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=j-davis-com.20230601.gappssmtp.com; s=20230601; t=1724876985; x=1725481785; darn=postgresql.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:from:to:cc:subject:date :message-id:reply-to; bh=sTKEtO8J/tqOll0mg5Q7aZ96mvBUHoDHSBUSf1GljIk=; b=jFmuhzjmRQIsr4STMLpC0KirbwZQJzeJxWI4T/0i3wpWAeOGMmJ/Ixe0+3+6xr+Rvn 84xco38x6vgGjl8Y/GUCxybgNxxm33flhsjtCQ2uF+vAEO58S4kllEeEAExoIKU+aBLg 2rzxD05Ta6QIrb5v3Ui4/V4I5fA6goAIqyg9mLH5Xi5ywsdaVVaXcMu/I0WHxpMKQed7 1c7+Cnk4qAYkIl9kKW/OQkQPUYfqq8OmEbwJZF3yoORVId0jr0I/qJ2NHzfoHiKga5NC ohmQowP1Zmuw+yNho8OZc3TXMm77RbvT8tyORs4oMsbwAfMjwfdymb4MUTk47neICku2 G+cQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724876985; x=1725481785; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=sTKEtO8J/tqOll0mg5Q7aZ96mvBUHoDHSBUSf1GljIk=; b=l/RXcc9YTWcn4tUgIrocmJT+arxQ8Dg8N7He6wSa9VrqLte+kxh66W9heTuLtKL4E3 4A6CHrLuNW6PoKY7OjpeJeh/ozOExw8LVhNjjZL6C0f5nYs06ksjhan7erf7Dzwq3JJE 5yAJ9QELRaieaUFLfrl2VsYdjpEOgs8ZJFXZAyX2FnH+TIXXx8KHN+gZqgYqjI3HEgag 7Yvt/N35Ax+KydT7uy7pCsQwoZGP0XSHgdT4jI+UtsHO5KdvHTfUswpc3Byl54RcP4nf yXaUnh5F7rs7GN023X6riLnSJwY4AoxD4SgfSS1kefM0S5EUEhUS/Z0RKzFYNMKrar5K tKPg== X-Forwarded-Encrypted: i=1; AJvYcCWiMyN4IUmMdBBQqEovSaEmYdosEhQ3y0V/CqZwyBETiVLg0ENnjuQIGwhQnyoji1BChwhA0Y+wRVaboiuO@postgresql.org X-Gm-Message-State: AOJu0YzY5edazETOkZ8cGj+uM9+nWMXdenTmgKK1XdL5XCMU/M7eEUPe yy7YhUe9VJ0dgxEGukbVsZ3GBolcHB1IYSTv9y3626ov0XshsRI3siclL9jKGw== X-Google-Smtp-Source: AGHT+IFFN8BtPiJ2nbBr+n+6Ue78PBVzIAukRWhgl/q/JPpYftUMKcXzv9pT31dHJoPMbPhHPef0eA== X-Received: by 2002:a05:6a21:3181:b0:1cc:9f2d:85f9 with SMTP id adf61e73a8af0-1cce10fe1bamr501275637.33.1724876984818; Wed, 28 Aug 2024 13:29:44 -0700 (PDT) Received: from [172.18.11.17] ([12.126.244.130]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-714342e442fsm10496539b3a.115.2024.08.28.13.29.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Aug 2024 13:29:44 -0700 (PDT) Message-ID: <95e423ea042a8d2f85c76ee28feb7a5b10265f4d.camel@j-davis.com> Subject: Re: allowing extensions to control planner behavior From: Jeff Davis To: Robert Haas , "pgsql-hackers@postgresql.org" Date: Wed, 28 Aug 2024 13:29:43 -0700 In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.44.4-0ubuntu2 MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, 2024-08-26 at 12:32 -0400, Robert Haas wrote: > I think there are two basic approaches that are possible here. If > someone sees a third option, let me know. First, we could allow users > to hook add_path() and add_partial_path().=20 ... > The other possible approach is to allow extensions to feed some > information into the planner before path generation and let that > influence which paths are generated. Preserving a path for the right amount of time seems like the primary challenge for most of the use cases you raised (removing paths is easier than resurrecting one that was pruned too early). If we try to keep a path around, that implies that we need to keep parent paths around too, which leads to an explosion if we aren't careful. But we already solved all of that for pathkeys. We keep the paths around if there's a reason to (a useful pathkey) and there's not some other cheaper path that also satisfies the same reason. Idea: generalize the idea of "pathkeys" to work for other reasons to preserve a path. Mechanically, a hint to use an index could work very similarly: come up with a custom reason to keep a path around, such as "a hint suggests we use index foo_idx for table foo", and assign it a unique number. If there's another hint that says we should also use index bar_idx for table bar, then that reason would get a different unique reason number. (In other words, the number of reasons would not be fixed; there could be one reason for each hint specified in the query, kind of like there could be many interesting pathkeys for a query.) Each Path would have a "preserve_for_these_reasons" bitmapset holding all of the non-cost reasons we are preserving that path. If two paths have exactly the same set of reasons, then add_path() would only keep the cheaper one. We could get fancy and have a compare_reasons_hook that would allow you to take two paths with the same reason and see if there are other factors to consider that would cause both to still be preserved (similar to pathkey length). I suspect that we might see interesting applications of this mechanism in core as well: for instance, track partition keys or other properties relevant to parallelism. That could allow us to keep parallel-friendly paths around and then decide later in the planning process whether to actually parallelize them or not. Once we've generalized the "reasons" mechnism, it would be easy enough to have a hook to add reasons to a path as it's being generated to be sure it's not lost. These hooks should probably be called in the individual create_*_path() functions where there's enough context to know what's happening. There could be many such hooks, but I suspect only a handful of important ones. This idea allows the extension author to preserve the right paths long enough to use set_rel_pathlist_hook/set_join_pathlist_hook, which can editorialize on costs or do its own pruning. Regards, Jeff Davis