pg.ddx.io  pgsql-performance@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Gabriel Biberian <admin@beemotechnologie.com>
To: pgsql-performance@postgresql.org
Subject: UPDATE on NOT JOIN
Date: Wed, 15 Feb 2012 19:33:49 +0100
Message-ID: <4F3BFA8D.1050200@beemotechnologie.com> (raw)

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



view thread (2+ messages)  latest in thread

Message-ID: <4F3BFA8D.1050200@beemotechnologie.com>
Permalink:  ../4F3BFA8D.1050200@beemotechnologie.com/
Also on:    postgresql.org/message-id/4F3BFA8D.1050200@beemotechnologie.com

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-performance@postgresql.org
  Cc: admin@beemotechnologie.com
  Subject: Re: UPDATE on NOT JOIN
  In-Reply-To: <4F3BFA8D.1050200@beemotechnologie.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox