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.92) (envelope-from ) id 1jGY3l-0002jd-Im for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Mar 2020 01:08:49 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1jGY3k-0004yQ-DH for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Mar 2020 01:08:48 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1jGY3j-0004yA-Q0 for pgsql-hackers@lists.postgresql.org; Tue, 24 Mar 2020 01:08:48 +0000 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jGY3h-0006lt-03 for pgsql-hackers@postgresql.org; Tue, 24 Mar 2020 01:08:46 +0000 Received: by mail-wm1-x344.google.com with SMTP id z18so1549205wmk.2 for ; Mon, 23 Mar 2020 18:08:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=6L+QQllAVd1DZDxg10PXcUeb/i0L3TxDaPL/7Qk6dTQ=; b=A/tprJfuRVDVtwdHnI1usBEiyCLmbwp/r0SnztQS8zk525YOOqNtxLygckrowLKOmq iuEwJmWkuRBpII6HoXW93tTCPuBKKn4S/SHbDp82J9lhMskRK0t9RmRIq5RH7uQEBj65 MAB+As6So8ACZXizoUCBq4EPjN8vIYKnHDLrm3y7rX8NGcOcTFuUajQHXrT3ZGl6ftP6 HXUHSXcSs2hDdTQP6oZOLSoy4xYIXTFvBopjXG/snXb2X2uDRsnBistMiUjaRxu7VrtZ DZaKaWdtYW/0ZxTmGwOrfCFGW+MdVHFYfEMz4idHhqXxkDRh8qRgW5Dusl4EfSCx62Be jUQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=6L+QQllAVd1DZDxg10PXcUeb/i0L3TxDaPL/7Qk6dTQ=; b=GUjVcWn4gk7lkeRypSnoMPYypyy1/KFGWh3oVv0OmqHhpOBOkIRcMK0MfAIcLm5xWQ neCGBqsQyPiY/Tu+eH/vHhMuowXte912rADhi4li49fImtRNXFRsCYoPxxcCNHQ8wpOe e0U2FGCpbRisphxZzS4btFaH7WiDWGk0KOay9a/FmEm0DowumSA8J70+H4rs0Qv77PLs 497860Xek8p9WY2YKTpnalbC4AuPC4c3iewCTg8L2LQ8ugcm0Sxqv16zGb14/fkd2EPl dCsrXHnoczV3zjMEGykjvh3/OG+KVGESSmizbck9nvmq2liZJO5R/m1VpPq5202ZQoJE gVSg== X-Gm-Message-State: ANhLgQ0SjfXOOxzAV3nqVwnyx7NLvRU5CUfFe9h3l8IMvE/iozvEaU/O 74/O0LEgTbPmTEEYvDb80voxVA== X-Google-Smtp-Source: ADFU+vu2TUa6fm6eyq5qj86zM66tDT0hKF21BlGox3xZzipY/OcUtGp8LsNlGWcJzERMdhauDqeuNg== X-Received: by 2002:a1c:6a03:: with SMTP id f3mr2302817wmc.178.1585012122487; Mon, 23 Mar 2020 18:08:42 -0700 (PDT) Received: from localhost (ip-86-49-253-92.net.upcbroadband.cz. [86.49.253.92]) by smtp.gmail.com with ESMTPSA id d21sm25923635wrb.51.2020.03.23.18.08.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 18:08:40 -0700 (PDT) Date: Tue, 24 Mar 2020 02:08:38 +0100 From: Tomas Vondra To: Dean Rasheed Cc: PostgreSQL Hackers Subject: Re: Additional improvements to extended statistics Message-ID: <20200324010838.hbv5gzhexcv5cilg@development> References: <20200309000157.ig5tcrynvaqu4ixd@development> <20200309000621.3jhvfxphagyf5bhg@development> <20200314165610.s7p2mgaishsujq5s@development> <20200315000809.ruwpx7ktnpnzly7c@development> <20200318193128.53soruotqdqnlaoy@development> <20200321215946.epx3dfi74stlwiab@development> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Mon, Mar 23, 2020 at 08:21:42AM +0000, Dean Rasheed wrote: >On Sat, 21 Mar 2020 at 21:59, Tomas Vondra wrote: >> >> Ah, right. Yeah, I think that should work. I thought there would be some >> volatility due to groups randomly not making it into the MCV list, but >> you're right it's possible to construct the data in a way to make it >> perfectly deterministic. So that's what I've done in the attached patch. >> > >Looking through those new tests, another issue occurred to me -- under >some circumstances this patch can lead to extended stats being applied >twice to the same clause, which is not great, because it involves >quite a lot of extra work, and also because it can lead to >overestimates because of the way that MCV stats are applied as a delta >correction to simple_sel. > >The way this comes about is as follows -- if we start with an OR >clause, that will be passed as a single-item implicitly AND'ed list to >clauselist_selectivity(), and from there to >statext_clauselist_selectivity() and then to >statext_mcv_clauselist_selectivity(). This will call >clauselist_selectivity_simple() to get simple_sel, before calling >mcv_clauselist_selectivity(), which will recursively compute all the >MCV corrections. However, the call to clauselist_selectivity_simple() >will call clause_selectivity() for each clause (just a single OR >clause in this example), which will now call >clauselist_selectivity_or(), which will go back into >statext_clauselist_selectivity() with "is_or = true", which will apply >the MCV corrections to the same set of clauses that the outer call was >about to process. > Hmmm. So let's consider a simple OR clause with two arguments, both covered by single statistics object. Something like this: CREATE TABLE t (a int, b int); INSERT INTO t SELECT mod(i, 10), mod(i, 10) FROM generate_series(1,100000); CREATE STATISTICS s (mcv) ON a,b FROM t; SELECT * FROM t WHERE a = 0 OR b = 0; Which is estimated correctly, but the calls graph looks like this: clauselist_selectivity statext_clauselist_selectivity statext_mcv_clauselist_selectivity <--- clauselist_selectivity_simple clause_selectivity clauselist_selectivity_or statext_clauselist_selectivity statext_mcv_clauselist_selectivity <--- clauselist_selectivity_simple_or clause_selectivity clause_selectivity mcv_clauselist_selectivity clauselist_selectivity_simple_or mcv_clauselist_selectivity clauselist_selectivity_simple (already estimated) IIUC the problem you have in mind is that we end up calling statext_mcv_clauselist_selectivity twice, once for the top-level AND clause with a single argument, and then recursively for the expanded OR clause. Indeed, that seems to be applying the correction twice. >I'm not sure what's the best way to resolve that. Perhaps >statext_mcv_clauselist_selectivity() / statext_is_compatible_clause() >should ignore OR clauses from an AND-list, on the basis that they will >get processed recursively later. Or perhaps estimatedclauses can >somehow be used to prevent this, though I'm not sure exactly how that >would work. I don't know. I feel uneasy about just ignoring some of the clauses, because what happens for complex clauses, where the OR is not directly in the AND clause, but is negated or something like that? Isn't it the case that clauselist_selectivity_simple (and the OR variant) should ignore extended stats entirely? That is, we'd need to add a flag (or _simple variant) to clause_selectivity, so that it calls causelist_selectivity_simple_or. So the calls would look like this: clauselist_selectivity statext_clauselist_selectivity statext_mcv_clauselist_selectivity clauselist_selectivity_simple <--- disable extended stats clause_selectivity clauselist_selectivity_simple_or clause_selectivity clause_selectivity mcv_clauselist_selectivity clauselist_selectivity_simple already estimated I've only quickly hacked clause_selectivity, but it does not seems very invasive (of course, it means disruption to clause_selectivity callers, but I suppose most call clauselist_selectivity). BTW do you have an example where this would actually cause an issue? regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services