X-Original-To: pgsql-performance-postgresql.org@localhost.postgresql.org Received: from localhost (unknown [200.46.204.144]) by svr1.postgresql.org (Postfix) with ESMTP id 0F30C52869 for ; Thu, 11 Aug 2005 09:34:04 -0300 (ADT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 19364-06 for ; Thu, 11 Aug 2005 12:34:02 +0000 (GMT) Received: from service-web.de (p15093784.pureserver.info [217.160.106.224]) by svr1.postgresql.org (Postfix) with ESMTP id 14F125285A for ; Thu, 11 Aug 2005 09:33:59 -0300 (ADT) Received: from [192.168.178.99] (p548B2D2C.dip0.t-ipconnect.de [84.139.45.44]) by service-web.de (Postfix) with ESMTP id 479EC200039; Thu, 11 Aug 2005 14:34:02 +0200 (CEST) Subject: Re: Speedier count(*) From: Tino Wildenhain To: PFC Cc: Gavin Sherry , Mark Cotner , Dan Harris , pgsql-performance@postgresql.org In-Reply-To: References: <1123745049.27613.1.camel@Andrea.peacock.de> <1123757536.27613.10.camel@Andrea.peacock.de> Content-Type: text/plain Date: Thu, 11 Aug 2005 14:34:00 +0200 Message-Id: <1123763640.27613.18.camel@Andrea.peacock.de> Mime-Version: 1.0 X-Mailer: Evolution 2.0.4 Content-Transfer-Encoding: 7bit X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, hits=0.098 tagged_above=0 required=5 tests=[AWL=0.048, FORGED_RCVD_HELO=0.05] X-Spam-Level: X-Archive-Number: 200508/117 X-Sequence-Number: 13864 Am Donnerstag, den 11.08.2005, 14:08 +0200 schrieb PFC: > > > You could lock the count table to prevent the problem > > where 2 competing transactions do an insert, read the > > start value and add 1 to it and then write the result > > - which is n+1 rather then n+2 - so you are off by one. > > Think of the same when one transaction inserts 100 > > and the other 120. Then you could even be off by 100. > > Niet. > > If your trigger does UPDATE counts_cache SET cached_count = > cached_count+N WHERE ... > Then all locking is taken care of by Postgres. > Of course if you use 2 queries then you have locking issues. Yes, in the case you use just the UPDATE statement you are right. This does the locking I was talking about. In either case I'd use an after trigger and not before to minimize the impact. > However the UPDATE counts_cache has a problem, ie. it locks this row FOR > UPDATE for the whole transaction, and all transactions which want to > update the same row must wait to see if the update commits or rollbacks, > so if you have one count cache row for the whole table you get MySQL style > scalability... > > To preserve scalability you could, instead of UPDATE, INSERT the delta of > rows inserted/deleted in a table (which has no concurrencies issues) and > compute the current count with the sum() of the deltas, then with a cron, > consolidate the deltas and update the count_cache table so that the deltas > table stays very small. Yes, this is in fact a better approach to this problem. (All this provided you want an unqualified count() - as the original poster)