Re: Performance implications of creating many, many sequences - Mailing list pgsql-general

From Craig Ringer
Subject Re: Performance implications of creating many, many sequences
Date
Msg-id 4CC25E94.8030602@postnewspapers.com.au
Whole thread Raw
In response to Performance implications of creating many, many sequences  (Michael Gardner <gardnermj@gmail.com>)
Responses Re: Performance implications of creating many, many sequences  (Michael Gardner <gardnermj@gmail.com>)
List pgsql-general
On 23/10/2010 3:18 AM, Michael Gardner wrote:
> Consider the following table:
>
> CREATE TABLE invoice (
>     account_id integer NOT NULL REFERENCES account,
>     invoice_number integer NOT NULL,
>     UNIQUE (account_id,invoice_number));
>
> I would like to do the equivalent of making invoice_number a serial type, but on a per-account basis. Would it be a
reasonableapproach to create a separate sequence for each individual account? Are there performance implications I
shouldknow about, given that there will be hundreds of thousands of accounts? Is there another approach I should be
lookingat instead? 

I'd favour "another approach". The purpose of sequences is to improve
concurrency in the face of rapid inserts. You're probably not going to
have a bunch of transactions all wanting to grab new invoice numbers for
the same customer at the same time, so this isn't going to be a problem;
you're already partitioning the concurrency limitation out to be
per-customer, which should be good enough.

Also, sequences are not gapless. If a transaction grabs an entry then
rolls back instead of committing, that ID is never used. Your customers
would probably not like that for invoice numbers.

Instead, maintain a counter, either in the main customer record or in an
associated (customer_id, counter) side table if you want to reduce
potential lock contention. Write a simple SQL function that uses an
UPDATE ... RETURNING statement to grab a new ID from the counter and
increment it. Use that function instead of 'nextval(seqname)' when you
want an ID. The UPDATE will take a lock out on the customer row (or
side-table row if you did it that way) that'll prevent anyone else
updating it until the transaction commits or rolls back.

--
Craig Ringer

Tech-related writing at http://soapyfrogs.blogspot.com/

pgsql-general by date:

Previous
From: Mike Christensen
Date:
Subject: Re: Missing uuid_generate_v1()
Next
From: quickinfo quickinfo
Date:
Subject: server error