Received: from maia.hub.org (maia-5.hub.org [200.46.204.29]) by mail.postgresql.org (Postfix) with ESMTP id 23FAB1337B64 for ; Tue, 16 Nov 2010 12:54:58 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.29]) (amavisd-maia, port 10024) with ESMTP id 68231-05 for ; Tue, 16 Nov 2010 16:54:50 +0000 (UTC) Received: from news.hub.org (news.hub.org [200.46.204.72]) by mail.postgresql.org (Postfix) with ESMTP id 3E4B81337B3E for ; Tue, 16 Nov 2010 12:54:50 -0400 (AST) Received: from news.hub.org (news.hub.org [200.46.204.72]) by news.hub.org (8.14.4/8.14.4) with ESMTP id oAGGsnYC096813 for ; Tue, 16 Nov 2010 12:54:49 -0400 (AST) (envelope-from news@news.hub.org) Received: (from news@localhost) by news.hub.org (8.14.4/8.14.4/Submit) id oAGGa7k3087831 for pgsql-performance@postgresql.org; Tue, 16 Nov 2010 12:36:07 -0400 (AST) (envelope-from news) From: Chris Browne X-Newsgroups: pgsql.performance Subject: Re: best db schema for time series data? Date: Tue, 16 Nov 2010 11:35:24 -0500 Organization: cbbrowne Computing Inc Lines: 74 Message-ID: <8762vxfcqb.fsf@cbbrowne.afilias-int.info> References: <20101116105055.GA26129@apartia.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Complaints-To: usenet@news.hub.org User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) Cancel-Lock: sha1:PZlkDz/WgTZKtKC6fqLXxuVA5K4= To: pgsql-performance@postgresql.org X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.91 tagged_above=-10 required=5 tests=BAYES_00=-1.9, T_RP_MATCHES_RCVD=-0.01 X-Spam-Level: X-Archive-Number: 201011/266 X-Sequence-Number: 41290 vindex+lists-pgsql-performance@apartia.org (Louis-David Mitterrand) writes: > I have to collect lots of prices from web sites and keep track of their > changes. What is the best option? > > 1) one 'price' row per price change: > > create table price ( > id_price primary key, > id_product integer references product, > price integer > ); > > 2) a single 'price' row containing all the changes: > > create table price ( > id_price primary key, > id_product integer references product, > price integer[] -- prices are 'pushed' on this array as they change > ); > > Which is bound to give the best performance, knowing I will often need > to access the latest and next-to-latest prices? I'd definitely bias towards #1, but with a bit of a change... create table product ( id_product serial primary key ); create table price ( id_product integer references product, as_at timestamptz default now(), primary key (id_product, as_at), price integer ); The query to get the last 5 prices for a product should be splendidly efficient: select price, as_at from price where id_product = 17 order by as_at desc limit 5; (That'll use the PK index perfectly nicely.) If you needed higher performance, for "latest price," then I'd add a secondary table, and use triggers to copy latest price into place: create table latest_prices ( id_product integer primary key references product, price integer ); create or replace function capture_latest_price () returns trigger as $$ declare begin delete from latest_prices where id_product = NEW.id_product; insert into latest_prices (id_product,price) values (NEW.id_product, NEW.price); return NEW; end $$ language plpgsql; create trigger price_capture after insert on price execute procedure capture_latest_price(); This captures *just* the latest price for each product. (There's a bit of race condition - if there are two concurrent price updates, one will fail, which wouldn't happen without this trigger in place.) -- "... Turns out that JPG was in fact using his brain... and I am inclined to encourage him to continue the practice even if it isn't exactly what I would have done myself." -- Alan Bawden (way out of context)