Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postgresql order by and limit

Tags:

sql

postgresql

I have a table R from which want to select the 3 predecessors or successor based on the z column. I have a btree index over the z column.

SELECT key, z, x, y FROM R
    WHERE z <= some_value
    ORDER BY z DESC 
    LIMIT 3

retrieves the predecessors in 'no time' but

SELECT key, z, x, y FROM R
    WHERE z >= some_value
    ORDER BY z ASC
    LIMIT 3

is useless for retrieving the next entries because is starts to scan through all the rows that have z >= some_value. Explain gives identical explanations on how the query is satisfied. Why is this and what could I do about it?

EDIT: There are two indexes actually, one ascending and one descending. Explain for both queries above says: "Limit (cost=0.00..31.91 rows=3 width=20)" " -> Index Scan Backward using zreverse on r (cost=0.00..17727815.24 rows=1666667 width=20)" " Filter: (z >= some_value")

like image 531
PLaine Avatar asked Oct 08 '12 10:10

PLaine


People also ask

Can we use LIMIT in PostgreSQL?

The PostgreSQL LIMIT clause is used to get a subset of rows generated by a query. It is an optional clause of the SELECT statement. The LIMIT clause can be used with the OFFSET clause to skip a specific number of rows before returning the query for the LIMIT clause.

How does LIMIT and offset work in PostgreSQL?

If a limit count is given, no more than that many rows will be returned (but possibly fewer, if the query itself yields fewer rows). LIMIT ALL is the same as omitting the LIMIT clause, as is LIMIT with a NULL argument. OFFSET says to skip that many rows before beginning to return rows.

How does PostgreSQL order by work?

The ORDER BY clause in PostgreSQL is used together with the SELECT statement to sort table data. The table data can either be sorted in ascending or descending order. By default, the data is sorted in ascending order.

What is the difference between LIMIT and offset?

The limit option allows you to limit the number of rows returned from a query, while offset allows you to omit a specified number of rows before the beginning of the result set. Using both limit and offset skips both rows as well as limit the rows returned.


2 Answers

Uhm...

some_value used in the WHERE clause is calculated by a simple function which was (falsely) defined VOLATILE. Changing it to STABLE solved the issue.

like image 81
PLaine Avatar answered Oct 09 '22 00:10

PLaine


Is the index on z an "ordinary" btree index with nothing else specified? Or was it created in "descending" order, ie as

create index <name> on R(z) desc;

?

Quite possibly the addition of the opposite order index to the one you have may help.

like image 28
Colin 't Hart Avatar answered Oct 08 '22 23:10

Colin 't Hart