Re: counting rows
Date: Sat, 1 Apr 2006 21:41:13 +0000 (UTC)
Message-ID: <slrne2tsrs.5n3.lefty_at_goedel.home.rtfm.gr>
On 2006-04-01, Tony Rogerson <tonyrogerson_at_sqlserverfaq.com> wrote:
You clearly want it correct, otherwise you don't want to evaluate count(*)
you want to evaluate something like 'estimate rows' which is a different
cettle of fish alltogether.
No locking is only an issue on /some/ databases.
e.g. in read commited isolation level (the default) with two transactions
both inserting into the same table neither Oracle nor PostgreSQL lock
the table. Both give the correct reply for count(*).
> I'll answer that question with another question - do you want it accurate?
> In which case you'll need to serialise anyway.
>
> Locking will be there anyway because of the inserting of the picture row
> data.
>
> The update of count is simply modifying 4 bytes on a single row which would
> be accessed via a unique index (very little IO), do you really think the
> contention will be with the update?
>
The contention will be because locking will be mandatory in the trigger since in order for the count to be correct the transactions will *have* to be serialised. IO has *nothing* to do with it. If you have to serialize you take a performance hit on concurrent transactions, no two ways about it.
> By doing COUNT(*) and serialising the query will cause considerable > contention because the COUNT(*) query will be a lot longer. >
open two sessions s1 & s2
s1: create table s (id int4 primary key); s1: set session characteristics as transaction isolation level serializable; s2: set session characteristics as transaction isolation level serializable; s1: begin work; s2: begin work; s1: insert into s values(1); s1: select * from s;
id
1
(1 row)
s1: select count(*) from s;
count
1
(1 row)
s2: select * from s;
id
(0 rows)
s2: select count(*) from s;
count
0
(1 row)
s2: insert into s values(2);
s2: select * from s;
id
2
(1 row)
s2: select count(*) from s;
count
1
(1 row)
s1: select * from s;
id
1
(1 row)
s1: insert into s values(3);
s1: select * from s;
id
1
3
(2 rows)
s1: select count(*) from s;
count
2
(1 row)
s2: commit;
s1: select * from s;
id
1
3
(2 rows)
s1: select count(*) from s;
count
2
(1 row)
s1: commit;
s1: select * from s;
id
1
2
3
(3 rows)
s1: select count(*) from s;
count
3
(1 row)
No locks, no contention (mind you I was careful not to insert using the same primary key - if I had done so then I would have had the following:
s1: begin work; s2: begin work; s1: insert into s values(4);
INSERT 0 1
s2: insert into s values(4);
------- Waiting for lock
s1: commit;
s2: prints ERROR: duplicate key violates unique constraint "s_pkey"
Lefty Kreouzis Received on Sat Apr 01 2006 - 23:41:13 CEST