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 1pPryp-0004fQ-82 for pgsql-hackers@arkaria.postgresql.org; Wed, 08 Feb 2023 21:27:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pPryn-00018x-Ss for pgsql-hackers@arkaria.postgresql.org; Wed, 08 Feb 2023 21:27:49 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pPryn-00018n-JE for pgsql-hackers@lists.postgresql.org; Wed, 08 Feb 2023 21:27:49 +0000 Received: from mail-ed1-x531.google.com ([2a00:1450:4864:20::531]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pPryl-00027m-5H for pgsql-hackers@lists.postgresql.org; Wed, 08 Feb 2023 21:27:48 +0000 Received: by mail-ed1-x531.google.com with SMTP id m8so294117edd.10 for ; Wed, 08 Feb 2023 13:27:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb.com; s=google; h=content-transfer-encoding:in-reply-to:from:references:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=KxJou0K5U4Hjil7BShMukuf/AnxCqtJt8allk5ClkVA=; b=SQZSzXrNjXqhOIuWL73defW5ggZlo61kWE0a+ztrhtRfNBk71eZV2MC+/ZTyoWDBED 49aeDZEmlDEJCaCMA9dNMHt/3p8AYz4zRsyFUEMe7XB2CQG06plCn1waDKHAFBpU9YgU AkzZDqe/C4p6qZhtNRe4K1QQ8NAhz4YY3kCe+oJto2SkkfPrFdW42UfoyFYyq3TSaoJi dbtkjJD4rlHujRNqxM8A2bOFn4eNsP9TF8iznQ799Y+6LpeXUGxORbeD1UBhSrLbf1aV zTJoHKk8QO6kyKQXvPhbxjpXTUogN8aMq+Jcb1Ih9d4iFY+Bs+kBxN3AEZyod5xiLB6B mONg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from: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=KxJou0K5U4Hjil7BShMukuf/AnxCqtJt8allk5ClkVA=; b=ZwIGWkKXk2Z22IW0aADFmKmcukiycL2upQgPUk8UDUirLPj44EbnBvKSS6GEXS0qbR RuuurL5NUEa7WssLo4YAbqRyy9V1q1+oXFi6pIxpZLXHw/+t7SnxUGaUnWbTIBq7ERBu TKcbgb18YPcuYDmieuEfC7CZcSgOO1sBQVpwa0Q+N3z/0rXNTVnuuQ4yxMYBlaqeO18Z rfyR2Hd0Y4EM5r3C1ZhETfvdaBKINaFICJ82amDVMvnMoSZrjHK2IQlF+3sR0BBWRt2T v+TyxwI8PMO/hkVwFznvzf/ql3JwFoQUv9ul7lsE4Q6HxeP7lQiK/KNgbtaKAPYT4Cr0 a0ww== X-Gm-Message-State: AO0yUKU/0Mp7kX3l7AWQrFy/v67/frRe/86x3lWUo1bMP0Z3umNh0DtF TbFWNRmsLZmCSw7bFL1OOMG8JD0TVLDtDJX0uVLNv2aXxhrgGJ9OgXmzJfPtiMs9Vh5fFafj3pN d9vJnLyN41X4N19ZT80HwyfQNHrs9TREefT3T77JjLvBAZZrH/IjFca1M+EIGMADWmfj0zXmrK0 xLmu1v6tAsMqEy+edODoLdteYatUxsa0zDWiA9u8p1yStnObPbOPYgpimCviqxjslZyU+BwEkyg ZLb0GZ6SLb/PoAmt4c05VRYTAUdAA0R/6uYMKDp76SaioQ5plE+b84QkiAzv4rp9Cf9AUQ= X-Google-Smtp-Source: AK7set9gdwzcJe0e7almHiwoGBROuo957t0UITgfYStWeKehqfuB/Dy9lRHBHponyVGJVCht7i6jOA== X-Received: by 2002:a50:9f6e:0:b0:4ab:1737:b4ea with SMTP id b101-20020a509f6e000000b004ab1737b4eamr882281edf.6.1675891665656; Wed, 08 Feb 2023 13:27:45 -0800 (PST) Received: from [10.137.0.17] (nat-106.starnet.cz. [178.255.168.106]) by smtp.gmail.com with ESMTPSA id dz16-20020a0564021d5000b004a0f9d31d18sm8430842edb.71.2023.02.08.13.27.45 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 08 Feb 2023 13:27:45 -0800 (PST) Message-ID: Date: Wed, 8 Feb 2023 22:27:46 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.7.1 Subject: Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Content-Language: en-US To: Hans Buschmann , "pgsql-hackers@lists.postgresql.org" References: <4504e67078d648cdac3651b2960da6e7@nidsa.net> From: Tomas Vondra In-Reply-To: <4504e67078d648cdac3651b2960da6e7@nidsa.net> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-CLOUD-SEC-AV-Info: enterprisedb,google_mail,monitor X-CLOUD-SEC-AV-Sent: true X-Gm-Spam: 0 X-Gm-Phishy: 0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 2/8/23 14:55, Hans Buschmann wrote: > During data refactoring of our Application I encountered $subject when > joining 4 CTEs with left join or inner join. > > > 1. Background > > PG 15.1 on Windows x64 (OS seems no to have no meening here) > > > I try to collect data from 4 (analyzed) tables (up,li,in,ou) by grouping > certain data (4 CTEs qup,qli,qin,qou) > > The grouping of the data in the CTEs gives estimated row counts of about > 1000 (1 tenth of the real value) This is OK for estimation. > > > These 4 CTEs are then used to combine the data by joining them. > > > 2. Problem > > The 4 CTEs are joined by left joins as shown below: > ... > > This case really brought me to detect the problem! > > The original query and data are not shown here, but the principle should > be clear from the execution plans. > > I think the planner shouldn't change the row estimations on further > steps after left joins at all, and be a bit more conservative on inner > joins. But the code should alredy do exactly that, see: https://github.com/postgres/postgres/blob/dbe8a1726cfd5a09cf1ef99e76f5f89e2efada71/src/backend/optimizer/path/costsize.c#L5212 And in fact, the second part of the plains shows it's doing the trick: -> Merge Left Join (cost=1293.25..1388.21 rows=5733 width=104) (actual time=2.321..2.556 rows=1415 loops=1) Merge Cond: ((qup_1.curr_season = qli_1.curr_season) AND ((qup_1.curr_code)::text = (qli_1.curr_code)::text)) -> Sort (cost=641.68..656.02 rows=5733 width=72) -> Sort (cost=651.57..666.11 rows=5816 width=72) But notice the first join (with rows=33) doesn't say "Left". And I see there's Append on top, so presumably the query is much more complex, and there's a regular join of these CTEs in some other part. We'll need to se the whole query, not just one chunk of it. FWIW it seems you're using materialized CTEs - that's likely pretty bad for the estimates, because we don't propagate statistics from the CTE. So a join on CTEs can't see statistics from the underlying tables, and that can easily produce really bad estimates. I'm assuming you're not using AS MATERIALIZED explicitly, so I'd bet this happens because the "cardinality" function is marked as volatile. Perhaps it can be redefined as stable/immutable. > This may be related to the fact that this case has 2 join-conditions > (xx_season an xx_code). That shouldn't affect outer join estimates this way (but as I explained above, the join does not seem to be "left" per the explain). Multi-column joins can cause issues, no doubt about it - but CTEs make it worse because we can't e.g. see foreign keys. regards -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company