Received: from localhost (unknown [200.46.208.211]) by mail.postgresql.org (Postfix) with ESMTP id 0DEAF632C85 for ; Wed, 23 Dec 2009 07:53:06 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.208.211]) (amavisd-maia, port 10024) with ESMTP id 30819-03 for ; Wed, 23 Dec 2009 11:52:48 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-yw0-f179.google.com (mail-yw0-f179.google.com [209.85.211.179]) by mail.postgresql.org (Postfix) with ESMTP id 9C9376328A8 for ; Wed, 23 Dec 2009 07:52:40 -0400 (AST) Received: by ywh9 with SMTP id 9so952110ywh.19 for ; Wed, 23 Dec 2009 03:52:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=uPSLTGdonPyYhX3S44OJPVDzEK5yeoSJpTn+hLcGT9g=; b=MWXbSg4LLhfGm2n9SYgbrvuc2BQU5AJgjAAaNs1WyxgtL5imuF72eSOgok/dXxRGit BZ+pbKA83LOEc+zIoUyI2H3t0tp65ySTcpY0hdSLTUr0OizGzwNCXlYklJYzUtzVj2uN MFKNfdL1/Y2q0NCkZQzPbyROQLQt+kwIiv/tA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=TmdKKjJvi+SU1r7cqziIm9aEa9eOzCFP4/zUX0rLEu0PkXX5lGOITkS/Racd2wW50+ JzsTdLf8CjZANrJwqgWzDsP5mZPXzVo/L5CeqakVLSCgNcZi8tBjGnS3hUcXb4MJFAjK UsHL4knQ+eGiuBpkOk3DCXWCQq38sMnP73B9c= MIME-Version: 1.0 Received: by 10.150.250.21 with SMTP id x21mr15460487ybh.181.1261569158442; Wed, 23 Dec 2009 03:52:38 -0800 (PST) In-Reply-To: <20091223115628.1709caf5@dawn.webthatworks.it> References: <20091222133527.3007bd96@dawn.webthatworks.it> <162867790912221147r7e3041fej44332a05faf915d6@mail.gmail.com> <20091223000031.54ad09b5@dawn.webthatworks.it> <20091223010940.51c5c069@dawn.webthatworks.it> <20091223024635.48d66554@dawn.webthatworks.it> <162867790912222338v73261b73u5c4e88a5ce85918f@mail.gmail.com> <20091223115628.1709caf5@dawn.webthatworks.it> Date: Wed, 23 Dec 2009 12:52:38 +0100 Message-ID: <162867790912230352v5b6e395fm1880111c04eaa626@mail.gmail.com> Subject: Re: short-cutting if sum()>constant From: Pavel Stehule To: Ivan Sergio Borgonovo Cc: pgsql-sql@postgresql.org Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-2.575 tagged_above=-10 required=5 tests=AWL=0.024, BAYES_00=-2.599 X-Spam-Level: X-Archive-Number: 200912/73 X-Sequence-Number: 33511 2009/12/23 Ivan Sergio Borgonovo : > On Wed, 23 Dec 2009 08:38:52 +0100 > Pavel Stehule wrote: > >> > As even more unexpected... when all row are >0 and most of them >> > are equal to 1 the generate_series performs appreciably better >> > (roughly 15% faster). >> > And I think your version can be further optimised: >> > select count(*) from (select (generate_series(1,a))::int from >> > data limit 90000000) s; >> > This perform 30% faster. >> > >> > So what's so slow in the plpgsql version? >> >> don't forget - plpgsql is interpret - it is best as glue for SQL > > Yeah but how many times is it interpreted in a 1M cycle expecially > when you ran it more than one time and the interpreter should be > "hot"? I don't know how much "interpreter" work can be saved from a > previous run of the function... but still there should be something > left [1]. > plpgsql isn't duck typed and that function doesn't leave too much > space for "interpretation". > Unless I'm missing something, in a typed language like plpgsql that > function could be easily turned into its C equivalent by the > interpreter. > I really thought the cost of running plpgsql was much lower in such > kind of situation. The problem is massive cycle. Plpgsql really isn't language for this. This interpret missing own arithmetic unit. So every expression is translated to SELECT statement IF a > c ~ SELECT a > c a =3D a + 1 ~ SELECT a + 1 these queries are executed in some special mode, but still it is more expensive than C a =3D a + 1 > > Consider that the cost doesn't come from the initial cost of > interpreting the function but it is proportional to the numbers of > cycles. > > Even hard coding the LIMIT in the plpgsql version doesn't make it > faster enough. So it is not the planner. > > In a 10M rows dataset where 8332885 are =3D1 and the rest are =3D2: > > If I'm testing for >900000 > I get 940.580 ms vs 1302.162 ms > If I'm testing for >9000000 > I get 8816.263 ms vs 12306.483 ms > > BTW > select sum(a) from data; takes 1999.492 ms. > select count(*) from data; takes 1612.039 ms > it is slower, because there is one NULL test more. > While smart your way is definitively more convoluted and should > require much more cpu cycles and memory. > > The plperl version: > create or replace function totano(int) > returns int as > $$ > =C2=A0 =C2=A0 =C2=A0 =C2=A0my $b =3D 0; > =C2=A0 =C2=A0 =C2=A0 =C2=A0my $row; > =C2=A0 =C2=A0 =C2=A0 =C2=A0my $sth =3D spi_query("select a from data"); > =C2=A0 =C2=A0 =C2=A0 =C2=A0while(defined($row=3Dspi_fetchrow($sth))) { > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0$b +=3D $row->{a}; > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if($b>=3D$_[0]) { > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0return $b; > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} > =C2=A0 =C2=A0 =C2=A0 =C2=A0} > =C2=A0 =C2=A0 =C2=A0 =C2=A0return $b; > $$ LANGUAGE plperl; > > Is 10 times slower than the plpgsql version. > PLpgSQL quietly uses cursors for FOR SELECT, your plperl uses normal standard recordset - it means so your query generate full scan. In your plperl code, you have to use explicit CURSORS. Then the speed should be comparable. Plperlu is little bit faster, but plpgsql has direct cursor support. >> statement. I don't thing so plpgsql is slow - speed is similar to >> using buildin functionality. But I am sure, rewritening your >> function to C could help. If you need maximal speed. > > In my case it is not worth. I was just looking into something that > didn't have to scan all the rows. > With the real distribution of data and no real workload on the box > your solution is faster but the difference while unexpectedly > appreciable is nearly negligible. > > Anyway I'm not able to justify the difference in speed between > plpgsql and your solution in such case unless plpgsql is switching > back and forward between binary data and their text representation. > It would be nice if someone that know plpgsql internals explain > where the cost comes from. I thing so most expensive part in your plpgsql code is two expression. Regards Pavel > >> I thing, so there are other trick, I am not sure if it is faster. >> You can create own aggregate. In state function you can calculate >> and check state value. If it is over your limit, then you can raise >> exception. So if your query will be finished with custom exception, >> then sum(c) > n is true. > > I may test it later. > > thanks > > -- > Ivan Sergio Borgonovo > http://www.webthatworks.it > > > -- > Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-sql >