Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84) (envelope-from ) id 1afECy-00062U-0q for pgsql-hackers@arkaria.postgresql.org; Sun, 13 Mar 2016 22:09:56 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84) (envelope-from ) id 1afECx-0000Gr-EF for pgsql-hackers@arkaria.postgresql.org; Sun, 13 Mar 2016 22:09:55 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84) (envelope-from ) id 1afECv-0000FI-AS for pgsql-hackers@postgresql.org; Sun, 13 Mar 2016 22:09:53 +0000 Received: from mail-wm0-x233.google.com ([2a00:1450:400c:c09::233]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84) (envelope-from ) id 1afECr-000486-Oy for pgsql-hackers@postgresql.org; Sun, 13 Mar 2016 22:09:51 +0000 Received: by mail-wm0-x233.google.com with SMTP id l68so84160775wml.0 for ; Sun, 13 Mar 2016 15:09:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=message-id:subject:from:to:cc:date:in-reply-to:references :mime-version:content-transfer-encoding; bh=iGRw5i3vqwG02DfhQaR7hISX7sdvtss2KJTNdqKsegk=; b=CYRzRTNR0OZS6X2t/p5HHeRUIQ3o3b9NfgKU3dyMiNoNESFDkq3R1qja6k+b5up9FD cY88x9xMxR9chckS82uLLGpwKXtObclTwYjQaDHZawFM0Wzafdi9J4E1K9UnnTarfh/L zSk2CJzwkUONx/Ry8X4U3Z3fHMH3G7drGReDrObHXnYWNHG8Z+QBmBnc8Ca7mFFj0zs1 OvZ2akQ8QZenX1dO39KIwtRSeDI2Wlpv9aeLCHk9EIp+4JKoZUBdQT0k1QAVl5Lo8L4q CtFAhhNVqx+4syFxKcA9l0MpqnZwY9Gl329CZmuYRClxZqigMqeeU6iur10mMCqQqDzl jqAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:mime-version:content-transfer-encoding; bh=iGRw5i3vqwG02DfhQaR7hISX7sdvtss2KJTNdqKsegk=; b=NniGSOH/CEj+n6NSxq2o5tZWJIZwSz2ZZuiRtgP/qnWQtjdtrn+X1KkOq7Wl77u2Ir qtgz/SA0CYidqN5lotLhr43oCDtdarCWpiVLO0DwC3lZYHQc9KW6XsMxSG3QUi8mqog0 nFGdnMicQofD4P7yf0PAsnO4SVM8H2zOzQlFO33tH3daS7xwW7PvXrAGJoeO4QCWLtsn 7sgNru8NdoGNVEJZqCE7woCvqdqG0SVMrQFBOMsWy7T8k1soiJuzuiqaNUmWVgzMnRf6 DcQBc76FoUwh2rFGSBeS0mxh0MEgT5pYoXyYv7t1relP4qGzDR9amYMRL0lT/vewD1nA iqxg== X-Gm-Message-State: AD7BkJJmL2gNuDChGBV7vuAl0cOCDn2/qPDnocd6612JPfurk1/RFa673bSKzXKblonBz9XO X-Received: by 10.194.185.180 with SMTP id fd20mr21706659wjc.98.1457906987346; Sun, 13 Mar 2016 15:09:47 -0700 (PDT) Received: from development (ip-78-45-216-26.net.upcbroadband.cz. [78.45.216.26]) by smtp.gmail.com with ESMTPSA id jo6sm19409377wjb.48.2016.03.13.15.09.46 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 13 Mar 2016 15:09:46 -0700 (PDT) Message-ID: <1457906984.27231.16.camel@2ndquadrant.com> Subject: Re: improving GROUP BY estimation From: Tomas Vondra To: Dean Rasheed Cc: Mark Dilger , Alexander Korotkov , PostgreSQL-development Date: Sun, 13 Mar 2016 23:09:44 +0100 In-Reply-To: References: <56CD0381.5060502@2ndquadrant.com> <03A3B58D-6A2D-44FE-9B03-E21948CFCBAA@gmail.com> <56CFA373.3060105@2ndquadrant.com> <7D1A65E8-7ED8-4268-9C24-8EA07E95D2BC@gmail.com> <56CFCE96.5080306@2ndquadrant.com> <56D867C3.3040309@2ndquadrant.com> <904EB795-BCDD-4D68-8D44-274B40C4B2E9@gmail.com> <56D88D93.5000509@2ndquadrant.com> <1457097036.24980.28.camel@2ndquadrant.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.18.5.1 (3.18.5.1-1.fc23) Mime-Version: 1.0 Content-Transfer-Encoding: 8bit X-Pg-Spam-Score: -2.6 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org Hi, On Sun, 2016-03-13 at 15:24 +0000, Dean Rasheed wrote: > On 4 March 2016 at 13:10, Tomas Vondra > wrote: > > > > The risk associated with over-estimation is that we may switch from > > HashAggregate to GroupAggregate, and generally select paths better > > suited for large number of rows. Not great, because the plan may > > not be > > optimal and thus run much slower - but that usually only happens on > > small tables, because on large tables we would probably end up > > using > > those same paths anyway. > > > > With under-estimation, the main risks are much graver, as we may > > end up > > using HashAggregate only to get killed by OOM. When we're lucky not > > to > > hit that, my experience this often leads to a cascade of NestedLoop > > nodes processing orders of magnitude more tuples than expected. > > Awful. > > > > So I think the risk is asymmetric, and that's why I like the new > > estimator more, because it tends to over-estimate, but in a very > > reasonable way. > > > Agreed. Under-estimating is worse than over-estimating. > > > -           reldistinct *= rel->rows / rel->tuples; > +           reldistinct *= (1 - powl((reldistinct - 1) / reldistinct, > rel->rows) > > Looking at this, I agree that this new formula from [1] is generally > better than the old one in most (but not all) cases. > > One problem with it is that it no longer takes into account > rel->tuples, which means that when returning all the tuples from the > table, it no longer gives an estimate equal to the total number of > distinct values in the table. In fact it tends to underestimate when > returning nearly all the rows from the table. Yes, that's a good point. > > The old formula is clearly not a good general-purpose estimate. > However, there is one case where it does return an accurate estimate > -- when all the values in the underlying table are distinct. In this > case the new formula consistently produces underestimates, while the > old formula works well. For example: > > CREATE TABLE t AS SELECT (100000000 * random())::int a, >                          i::int b >                     FROM generate_series(1,1000000) s(i); > ANALYSE t; > > EXPLAIN ANALYSE > SELECT a FROM t GROUP BY a; > > So there are clearly around 1 million distinct values for "a", but > the new formula gives an estimate of around 630,000. That's not a > massive underestimate, but it's sufficiently obvious and visible that > it would be good to do better if we can. > > > I think that a better formula to use would be > > reldistinct *= (1 - powl(1 - rel-rows / rel->tuples, rel->tuples / > reldistinct) > > This comes from [2], which gives a general formula for selection > without replacement, and then gives the above as an approximation to > the uniform distribution case. It's not really made clear in that > paper, but that approximation is actually the "with replacement" > approximation, but starting from different initial assumptions to > give a formula that has better boundary conditions and special-case > behaviour, as described below. > > ... > > For most values of N and n, the approximation from [2] is almost > indistinguishable from the exact formula, whereas the formula from > [1] tends to underestimate when selecting a large number of distinct > values (e.g., try setting n=900000 in the plot above). Yes, I agree that formula you propose seems to behave better. regards -- Tomas Vondra                  http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers