Received: from magus.postgresql.org (magus.postgresql.org [87.238.57.229]) by mail.postgresql.org (Postfix) with ESMTP id 3B4BB89E970 for ; Wed, 15 Feb 2012 14:34:09 -0400 (AST) Received: from mail-we0-f174.google.com ([74.125.82.174]) by magus.postgresql.org with esmtp (Exim 4.72) (envelope-from ) id 1Rxjg5-0003Q3-Iy for pgsql-performance@postgresql.org; Wed, 15 Feb 2012 18:34:09 +0000 Received: by werb13 with SMTP id b13so817794wer.19 for ; Wed, 15 Feb 2012 10:33:52 -0800 (PST) Received: by 10.216.131.100 with SMTP id l78mr3028706wei.44.1329330832381; Wed, 15 Feb 2012 10:33:52 -0800 (PST) Received: from Macintosh.local ([85.118.40.250]) by mx.google.com with ESMTPS id gd8sm35221357wib.2.2012.02.15.10.33.50 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 15 Feb 2012 10:33:51 -0800 (PST) Message-ID: <4F3BFA8D.1050200@beemotechnologie.com> Date: Wed, 15 Feb 2012 19:33:49 +0100 From: Gabriel Biberian Reply-To: gabriel.biberian@beemotechnologie.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0.1) Gecko/20120208 Thunderbird/10.0.1 MIME-Version: 1.0 To: pgsql-performance@postgresql.org Subject: UPDATE on NOT JOIN Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Gm-Message-State: ALoCoQk3SA2rzeHJd33VgHu+KRs8YaqDgq1bcq5cYOTTzIc+b7CZzgx/gWfJgokZfeLwYnX3J9yF X-Pg-Spam-Score: -2.6 (--) X-Archive-Number: 201202/119 X-Sequence-Number: 46291 Hello, I'm working on a system that detects changes in someone's filesystem. We first scan the entire filesystem which is dumped into the table 'filesystem' containing the full_path of every file and it's corresponding md5 hash. We then do subsequent scans of the filesystem which are dumped into a temporary table and we would like to find out which files are not present anymore. To do so, we update the field 'dead' in the 'filesystem' table for every row that does not exist in the 'temporary' table. \d filesystem; Table « public.filesystem » Colonne | Type | Modificateurs ------------+------------------------+---------------------- hash | character(32) | full_name | text | dead | integer | default 0 Index : « filesystem_unique » UNIQUE, btree (hash) \d temporary; Table « public.filesystem » Colonne | Type | Modificateurs ------------+------------------------+---------------------- hash | character(32) | full_name | text | Index : « temporary_unique » UNIQUE, btree (hash) Currently, i use the following query to update the filesystem table with the missing files : UPDATE filesystem SET dead=some_value WHERE dead=0 AND (SELECT 1 FROM temporary AS t WHERE t.hash=filesystem.hash LIMIT 1) IS NULL This works correctly for regular filesystems. But when the 'filesystem' table contains more than a few million rows, the update query can take days. Here's an explain of the query : =# UPDATE filesystem SET dead=some_value WHERE dead=0 AND (SELECT 1 FROM temporary AS t WHERE t.hash=filesystem.hash LIMIT 1) IS NULL QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Seq Scan on filesystem (cost=0.00..97536479.02 rows=25747 width=241) Filter: ((dead = 0) AND ((subplan) IS NULL)) SubPlan -> Limit (cost=0.00..9.53 rows=1 width=0) -> Index Scan using temporary_hash on temporary t (cost=0.00..9.53 rows=1 width=0) Index Cond: (hash = $0) (6 lignes) Is there a better way to update a table if it doesn't join another table ? Best Regards, Gabriel Biberian