Received: from localhost (maia-3.hub.org [200.46.204.184]) by postgresql.org (Postfix) with ESMTP id 44CDC9FB75F for ; Thu, 7 Jun 2007 19:48:16 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.184]) (amavisd-maia, port 10024) with ESMTP id 34203-01 for ; Thu, 7 Jun 2007 19:48:06 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey-1.7.5 Received: from mail.emolecules.com (66-226-76-106.dedicated.abac.net [66.226.76.106]) by postgresql.org (Postfix) with ESMTP id 68E449FC180 for ; Thu, 7 Jun 2007 19:48:12 -0300 (ADT) Received: (qmail 29961 invoked by uid 2020); 7 Jun 2007 15:48:10 -0700 Received: from wsip-68-224-174-233.sd.sd.cox.net (HELO ?192.168.0.3?) (68.224.174.233) by 192.168.0.4 with SMTP; 7 Jun 2007 15:48:09 -0700 Message-ID: <46688BC5.3020006@emolecules.com> Date: Thu, 07 Jun 2007 15:50:45 -0700 From: Craig James User-Agent: Thunderbird 1.5.0.12 (X11/20070509) MIME-Version: 1.0 To: "Tyrrill, Ed" CC: pgsql-performance@postgresql.org Subject: Re: Best way to delete unreferenced rows? References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0.217 tagged_above=0 required=5 tests=AWL=-0.234, BAYES_50=0.001, FORGED_RCVD_HELO=0.135, SARE_MILLIONSOF=0.315 X-Spam-Level: X-Archive-Number: 200706/143 X-Sequence-Number: 25176 Tyrrill, Ed wrote: > I have a table, let's call it A, whose primary key, a_id, is referenced > in a second table, let's call it B. For each unique A.a_id there are > generally many rows in B with the same a_id. My problem is that I want > to delete a row in A when the last row in B that references it is > deleted. Right now I just query for rows in A that aren't referenced by > B, and that worked great when the tables were small, but it takes over > an hour now that the tables have grown larger (over 200 million rows in > B and 14 million in A). The delete has to do a sequential scan of both > tables since I'm looking for what's not in the indexes. > > I was going to try creating a trigger after delete on B for each row to > check for more rows in B with the same a_id, and delete the row in A if > none found. In general I will be deleting 10's of millions of rows from > B and 100's of thousands of rows from A on a daily basis. What do you > think? Does anyone have any other suggestions on different ways to > approach this? Essentially what you're doing is taking the one-hour job and spreading out in little chunks over thousands of queries. If you have 10^7 rows in B and 10^5 rows in A, then on average you have 100 references from B to A. That means that 99% of the time, your trigger will scan B and find that there's nothing to do. This could add a lot of overhead to your ordinary transactions, costing a lot more in the long run than just doing the once-a-day big cleanout. You didn't send the specifics of the query you're using, along with an EXPLAIN ANALYZE of it in operation. It also be that your SQL is not optimal, and that somebody could suggest a more efficient query. It's also possible that it's not the sequential scans that are the problem, but rather that it just takes a long time to delete 100,000 rows from table A because you have a lot of indexes. Or it could be a combination of performance problems. You haven't given us enough information to really analyze your problem. Send more details! Craig