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 1qA8zw-0005CD-GC for pgsql-bugs@arkaria.postgresql.org; Fri, 16 Jun 2023 12:56:16 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1qA8zu-0007k9-Cr for pgsql-bugs@arkaria.postgresql.org; Fri, 16 Jun 2023 12:56:14 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qA8zu-0007k0-1X for pgsql-bugs@lists.postgresql.org; Fri, 16 Jun 2023 12:56:14 +0000 Received: from mail-ej1-x62f.google.com ([2a00:1450:4864:20::62f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1qA8zr-002n0I-1F for pgsql-bugs@lists.postgresql.org; Fri, 16 Jun 2023 12:56:13 +0000 Received: by mail-ej1-x62f.google.com with SMTP id a640c23a62f3a-982c996a193so91311066b.3 for ; Fri, 16 Jun 2023 05:56:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1686920170; x=1689512170; h=content-transfer-encoding:in-reply-to:from:cc:references:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=YWbRT6s97Dre+ihmL50xJfwjzjExKvrm9gvnPm7IpZw=; b=hRlBfy6oTFLp8hIaocqkW9cEBSCMAkc1XSciiB7Ldajs3YrQnQ582cvN9VtAi/rwey HY+XevPiLT+53Z8zTp9L7bOI0yJJaP1okFK2d3epPLoJzbhBUfQCDlWqheus/aIyUor/ 5BLWeNbCQ/SKHE5RMEWaQT2V23qXzP6+pK60JvhoUlPs75bntVU77O4A/SmfZ2ysGB3k /6Xz4eWjtr6XzpWfugIfRvnMacf6dgaSnCACDSApyEvxGMJ3I4AAq8aTDJRQKMLDvfqW 0fB+OQooF4yuNAqQuVht/g7CC+g58nC69erSW/WjY/D+7SMp86qyLYxWRR+goM/Q2BuI t3og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686920170; x=1689512170; h=content-transfer-encoding:in-reply-to:from:cc:references:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=YWbRT6s97Dre+ihmL50xJfwjzjExKvrm9gvnPm7IpZw=; b=hIJIGLybxGsd1bJ0tMdb7U9mpaxuh+jpbqDptAyLNcLXN25ej8AxPfJiys1q5LwAU6 Kds1Wjal2618fcZSzfhEAZMCQepAwyZ+Rl/lRT1xShok8wBgmjfZH84EURgNxZNRRLVR UeoyY2OVqVQwdEoHQG9+hK7HwxXSi/9GPNKlu+F0CRyiDpTrV6O5sVqD5+ddisgX4aEM jWDFbDiknHMNV3xEx+bZvs1GXq7Nd3s+6PAe3k8grsfK4so8Gxc1XzF4OYeF5fSxWn8f svmUF4ibPwgC1s/PC1/3CEFTfYSv6BGujLeiCKfpLWgOhG0A/R0EDKctKKO8fHdM78rh dbEg== X-Gm-Message-State: AC+VfDyq+GRrEN4A50RsVSOH1btfjvjItETDNZ5cFRBPXWzqd0ps4rOR 8HB+q5Sh5H/Z20GHx9D0fFOYXyfiTwg= X-Google-Smtp-Source: ACHHUZ7Io68vLtbDmS6VboxFpU/LOIkZCQhL6kqaGXIyYKUGQer3fLWlWFveX2qR6Y39vTCf73Dkbg== X-Received: by 2002:a17:907:8688:b0:973:e349:43c8 with SMTP id qa8-20020a170907868800b00973e34943c8mr2030571ejc.69.1686920169702; Fri, 16 Jun 2023 05:56:09 -0700 (PDT) Received: from ?IPV6:2a02:8388:e002:8cf0:6de8:96d4:442e:8a73? (2a02-8388-e002-8cf0-6de8-96d4-442e-8a73.cable.dynamic.v6.surfer.at. [2a02:8388:e002:8cf0:6de8:96d4:442e:8a73]) by smtp.googlemail.com with ESMTPSA id x18-20020a1709065ad200b00985767aa177sm970191ejs.202.2023.06.16.05.56.08 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 16 Jun 2023 05:56:09 -0700 (PDT) Message-ID: Date: Fri, 16 Jun 2023 14:56:07 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Subject: Re: BUG #17964: Missed query planner optimization Content-Language: de-AT To: David Rowley References: <17964-cdeb9e3f89c18393@postgresql.org> <94608857-707f-55ce-99a0-ac500aeb06f8@gmail.com> <8ca5637b-32c4-cb17-2de6-10f9248c5857@gmail.com> Cc: pgsql-bugs@lists.postgresql.org From: Mathias Kunter In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > We'd need a way to determine which is cheaper based on estimated costs Yes, that decision must of course be based on estimated costs, and also the cost estimation must be reasonably accurate. In all examples which I've seen so far, the cost estimations were adequate. > that might be, in my opinion, fairly tricky to do based on the order of > how things currently are done in the query planner. I don't know the details about the current planner implementation, but the planner obviously can already correctly estimate costs for both the IN and ANY(ARRAY()) variants. > I was just trying to show that it's quite a tricky problem to > fix properly. Yes, the tricky part obviously is to decide whether or not an IN clause should be converted to a semi-join, because that decision depends on the other IN clauses of the query as well. So, it's unfortunately not possible to decide independently for each IN clause. As you've already pointed out, doing an exhaustive search of all possible combinations is obviously problematic, since we'd have to check 2^N possible query plans (with N being the number of IN clauses of the query). So, this is certainly NOT the way to go, unless maybe N<4 or so. > Having the planner consider the costs of converting the IN to a semi- > join and converting or not based on cost seems like a worthy goal. It obviously is. As shown, the performance improvement can be gigantic for certain queries. > If you think it's quite an easy project, then we'll welcome > contributions to improve this. I'm not familiar with the current implementation, but my understanding is that this should be quite easy to implement for someone who is currently working on planner-related issues. After all, a reasonable heuristic solution can be as simple as this: 1) Create the query plan for the original query, using the current planner implementation. (That's the status quo.) 2) Create a modified version of the original input query where all of the IN clauses are replaced with ANY(ARRAY()). Create the query plan for that modified query version, using the current planner implementation. 3) Compare the two previously created query plans and execute the one with the lower estimated total cost. If you don't trust the planner's cost estimations for some reason, then only execute the modified version if its estimated cost is SIGNIFICANTLY lower. A simple solution like this would already be good enough to avoid many of the horrifying worst case scenarios, where a query takes minutes when it should actually only take milliseconds. It would of course be possible (and desirable) to come up with a more sophisticated heuristic than the one given above. For example, create a third version of the original query where only those IN clauses are replaced with ANY(ARRAY()) where the estimated number of rows returned by the subselect is below a certain threshold, and estimate costs for that modified query as well. > The pgsql-hackers as a good emailing list to bring up the topic Thank you for the hint. I'll continue the discussion over there. Mathias