X-Original-To: pgsql-performance-postgresql.org@localhost.postgresql.org Received: from localhost (av.hub.org [200.46.204.144]) by svr1.postgresql.org (Postfix) with ESMTP id 969F0DB326 for ; Sat, 29 Oct 2005 11:24:50 -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 47280-02 for ; Sat, 29 Oct 2005 14:24:44 +0000 (GMT) Received: from tigger.fuhr.org (tigger.fuhr.org [63.214.45.158]) by svr1.postgresql.org (Postfix) with ESMTP id 0BCB1DABC4 for ; Sat, 29 Oct 2005 11:24:45 -0300 (ADT) Received: from winnie.fuhr.org (winnie.fuhr.org [10.1.0.1]) by tigger.fuhr.org (8.13.3/8.13.3) with ESMTP id j9TEOWNW008705 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 29 Oct 2005 08:24:35 -0600 (MDT) (envelope-from mfuhr@winnie.fuhr.org) Received: from winnie.fuhr.org (localhost [127.0.0.1]) by winnie.fuhr.org (8.13.4/8.13.4) with ESMTP id j9TEOWdn079717; Sat, 29 Oct 2005 08:24:32 -0600 (MDT) (envelope-from mfuhr@winnie.fuhr.org) Received: (from mfuhr@localhost) by winnie.fuhr.org (8.13.4/8.13.4/Submit) id j9TEOWQ7079716; Sat, 29 Oct 2005 08:24:32 -0600 (MDT) (envelope-from mfuhr) Date: Sat, 29 Oct 2005 08:24:32 -0600 From: Michael Fuhr To: Martin Lesser Cc: pgsql-performance@postgresql.org Subject: Re: Effects of cascading references in foreign keys Message-ID: <20051029142432.GA79557@winnie.fuhr.org> References: <87acgszihk.fsf@nb-aspire.bettercom.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87acgszihk.fsf@nb-aspire.bettercom.de> X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, score=0.006 required=5 tests=[AWL=0.006] X-Spam-Score: 0.006 X-Spam-Level: X-Archive-Number: 200510/451 X-Sequence-Number: 15219 > Does an UPDATE of e.g. m_fld1 in t_master cause a 'lookup' in all tables > which have a cascading update-rule or is this 'lookup' only triggered if > the referenced column in t_master is explicitly updated? My tests suggest that a lookup on the referring key is done only if the referenced key is changed. Here's an example from 8.1beta4; I used this version because EXPLAIN ANALYZE shows triggers and the time spent in them, but I see similar performance characteristics in earlier versions. I've intentionally not put an index on the referring column to make lookups on it slow. CREATE TABLE foo (id serial PRIMARY KEY, x integer NOT NULL); CREATE TABLE bar (fooid integer NOT NULL REFERENCES foo ON UPDATE CASCADE); INSERT INTO foo (x) SELECT * FROM generate_series(1, 100000); INSERT INTO bar (fooid) SELECT * FROM generate_series(1, 100000); ANALYZE foo; ANALYZE bar; EXPLAIN ANALYZE UPDATE foo SET x = 1 WHERE id = 100000; QUERY PLAN --------------------------------------------------------------------------------------------------------------- Index Scan using foo_pkey on foo (cost=0.00..3.01 rows=1 width=10) (actual time=0.059..0.070 rows=1 loops=1) Index Cond: (id = 100000) Total runtime: 0.633 ms (3 rows) EXPLAIN ANALYZE UPDATE foo SET x = 1, id = 200000 WHERE id = 100000; QUERY PLAN -------------------------------------------------------------------------------------------------------------- Index Scan using foo_pkey on foo (cost=0.00..3.01 rows=1 width=6) (actual time=0.082..0.092 rows=1 loops=1) Index Cond: (id = 100000) Trigger for constraint bar_fooid_fkey: time=232.612 calls=1 Total runtime: 233.073 ms (4 rows) I'm not sure if this is the right place to look, but I see several places in src/backend/utils/adt/ri_triggers.c with code that looks like this: /* * No need to do anything if old and new keys are equal */ if (ri_KeysEqual(pk_rel, old_row, new_row, &qkey, RI_KEYPAIR_PK_IDX)) { heap_close(fk_rel, RowExclusiveLock); return PointerGetDatum(NULL); } > After removing some detail tables which are not longer needed we > see an improvemed performance so at the moment it _looks_ like each > update in t_master triggers a 'lookup' in each referencing table > also if the referenced column (m_id) is not changed. Do you have statistics enabled? You might be able to infer what happens by looking at pg_stat_user_tables or pg_statio_user_tables before and after an update, assuming that no concurrent activity is also affecting the statistics. I suppose there's overhead just from having a foreign key constraint, and possibly additional overhead for each constraint. If so then that might explain at least some of the performance improvement. Maybe one of the developers will comment. -- Michael Fuhr