In our online competition system, the standings table with whole columns (user_id, score) often changes. Both are indexed with a unique restriction. Two types of queries are required:
- Given a
score not in the table, return the position based on 1, which will occupy the score if it is inserted. - Given
user_id in the table, return the position of the corresponding rating.
In both cases, the position in relation to the account increases: a new assessment, smaller than everything currently in the table, will have position 1.
Here's the tricky part: we probably can't afford to scan the table. The table can have up to 10 million records, and we need to process at least 40 queries per second.
How to do it in PostgreSQL?
I have a non-SQL solution in Berkeley DB that uses B-trees with support for logical records. It easily has good performance. But we would like to get rid of BDB by re-implementing it using a PostgreSQL query. I tried the obvious
select 1+count(*) from standings where score < ? limit 1;
This causes a table scan.
I expect the answer to be βin no wayβ because the BDB logical record set facility requires locking the entire B-tree for each edit. To get O (log N) performance, it relies on the number of sheets in each node. All these calculations on the way to the root should change with each editing; hence locking. Such a lock contradicts PostgreSQL design principles and, possibly, any multi-user database.
So, if the problem cannot be solved with PostgreSQL, confirming this is the next best result of this question.
source share