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 1jGkcL-0004MM-Gk for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Mar 2020 14:33:21 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1jGkcJ-0005ix-Sq for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Mar 2020 14:33:19 +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 1jGkcJ-0005ip-GK for pgsql-hackers@lists.postgresql.org; Tue, 24 Mar 2020 14:33:19 +0000 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jGkcC-0004bs-Ke for pgsql-hackers@postgresql.org; Tue, 24 Mar 2020 14:33:17 +0000 Received: by mail-wm1-x32b.google.com with SMTP id a81so3634882wmf.5 for ; Tue, 24 Mar 2020 07:33:12 -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=nMHLfLdw+/Tlf+Y+YJt+HfQzUyF3Tun1ummRoMJMdEQ=; b=fVJo4oUApLnXXMyQAG+HEirc3ZXlxrEBb70Rs4+7YcaPnH+gpxn7PeXSFQ5+psy8an OtbQp9X6wqiyxPwBnKy0ki1E808ZWDz6psMBch0keDJq+513ovtnzqlkIqnk9c2POxIA Ltm5yHzoCLU6xTJNZwTus25KUbTloNuzIxyANmRDXfInECe+06BwBwucP0cMRUSNsDhJ Wmq1zCmi33iqaRpxrk0GZNHQFRRgibsJFbvD217drGUZQ6E07i+ookeJh3YdTJADv3CH HZmhex1svps84BLeHNXE3sBtRhTv0l8XG08NM4WkzLpEQMDtmq0FbgKcTLQcbHtdndek hIBQ== 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=nMHLfLdw+/Tlf+Y+YJt+HfQzUyF3Tun1ummRoMJMdEQ=; b=pk/PbJe9ALte+Egh1f2h4bwhmhBnHeZGZ9zmynpA6pFYERSqyn0Fjk8iEJFLsl1Bpk Q/1alv7BmP3YR8DB9lN0qkZXfO/pSRCUKb8oEP5iLUu6gAYMJ2vzAKgW/5XZIg2vNAyU fpPzsDbeFKls+q1Ge0a1diHrLhzmlf8L5k7q9+VnKs5xdyDqfFom8H7o9zs/0DWIEI2g mimU4W7Vc/rfTu7/pmWJTTyelVWAH6VakPPEz8hd9WQd3gDOMwAf+4ZHU5eI31uq7hgB X5lvQJ6uOcnDA4lbeLFNV9m+JwrmVlXKtOQFtRhpX1ywF1JDEipYp/jLWDGyll3fY2q7 Ey/g== X-Gm-Message-State: ANhLgQ05L1MnOgVzRNGPW6ejCZLQoZHEHQkFSEuQtGAAmcDoyFkP02nu XW+GhTWeuBitktYOUmtf3Kk2Ig== X-Google-Smtp-Source: ADFU+vsXVgNLDygsxlMtfkiY3z+1BBq8H/C7oRb4/s0UubY+qLeKusezCq2s+VP1Yb2RTZ1jJMmLVA== X-Received: by 2002:a7b:c388:: with SMTP id s8mr5878484wmj.168.1585060390841; Tue, 24 Mar 2020 07:33:10 -0700 (PDT) Received: from localhost (ip-86-49-253-92.net.upcbroadband.cz. [86.49.253.92]) by smtp.gmail.com with ESMTPSA id o133sm4579315wme.35.2020.03.24.07.33.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Mar 2020 07:33:09 -0700 (PDT) Date: Tue, 24 Mar 2020 15:33:06 +0100 From: Tomas Vondra To: Dean Rasheed Cc: PostgreSQL Hackers Subject: Re: Additional improvements to extended statistics Message-ID: <20200324143306.rz5siohm4jsoveqm@development> References: <20200314165610.s7p2mgaishsujq5s@development> <20200315000809.ruwpx7ktnpnzly7c@development> <20200318193128.53soruotqdqnlaoy@development> <20200321215946.epx3dfi74stlwiab@development> <20200324010838.hbv5gzhexcv5cilg@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 Tue, Mar 24, 2020 at 01:20:07PM +0000, Dean Rasheed wrote: >On Tue, 24 Mar 2020 at 01:08, Tomas Vondra wrote: >> >> 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... >> > >Hmm, the reason that is estimated correctly is that the MCV values >cover all values in the table, so mcv_totalsel is 1 (or pretty close >to 1), and other_sel is capped to nearly 0, and so the result is >basically just mcv_sel -- i.e., in this case the MCV estimates are >returned more-or-less as-is, rather than being applied as a >correction, and so the result is independent of how many times >extended stats are applied. > >The more interesting (and probably more realistic) case is where the >MCV values do not cover the all values in the table, as in the new >mcv_lists_partial examples in the regression tests, for example this >test case, which produces a significant overestimate: > > SELECT * FROM mcv_lists_partial WHERE a = 0 OR b = 0 OR c = 0 > >although actually, I think there's another reason for that (in >addition to the extended stats correction being applied twice) -- the >way the MCV code makes use of base selectivity doesn't seem really >appropriate for OR clauses, because the way base_frequency is computed >is really based on the assumption that every column would be matched. >I'm not sure that there's any easy answer to that though. I feels like >what's needed when computing the match bitmaps in mcv.c, is to produce >a bitmap (would it fit in 1 byte?) per value, to indicate which >columns match, and base_frequency values per column. That would be >significantly more work though, so almost certainly isn't feasible for >PG13. > Good point. I haven't thought about the base frequencies. I think 1 byte should be enough, as we limit the number of columns to 8. >> 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). >> > >Sounds like a reasonable approach, but I think it would be better to >preserve the current public API by having clauselist_selectivity() >become a thin wrapper around a new function that optionally applies >extended stats. > OK, makes sense. I'll take a stab at it. regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services