Sql 利用大表上的偏移量优化查询

Sql 利用大表上的偏移量优化查询,sql,postgresql,pagination,sql-order-by,postgresql-9.5,Sql,Postgresql,Pagination,Sql Order By,Postgresql 9.5,我有一张桌子 create table big_table ( id serial primary key, -- other columns here vote int ); 这个表非常大,大约7000万行,我需要查询: SELECT * FROM big_table ORDER BY vote [ASC|DESC], id [ASC|DESC] OFFSET x LIMIT n -- I need this for pagination 您可能知道,当x是一个大数字时,像这样的查询非

我有一张桌子

create table big_table (
id serial primary key,
-- other columns here
vote int
); 
这个表非常大,大约7000万行,我需要查询:

SELECT * FROM big_table
ORDER BY vote [ASC|DESC], id [ASC|DESC]
OFFSET x LIMIT n  -- I need this for pagination
您可能知道,当
x
是一个大数字时,像这样的查询非常慢

对于性能优化,我添加了索引:

create index vote_order_asc on big_table (vote asc, id asc);

EXPLAIN
显示上面的
SELECT
查询使用了这些索引,但是速度非常慢,偏移量很大


如何在大表中使用
OFFSET
优化查询?也许PostgreSQL 9.5或更高版本有一些功能?我搜索过了,但什么也没找到。

你试过划分桌子了吗

易于管理、改进的可扩展性和可用性,以及 减少阻塞是划分表的常见原因。 提高查询性能并不是采用分区的理由, 虽然在某些情况下,这可能是一种有益的副作用。依据 在性能方面,确保您的实施计划 包括对查询性能的检查。确认您的索引 在创建表之后,继续适当地支持您的查询 已分区,并验证使用群集和 非聚集索引受益于分区消除,其中 适用


较大的
偏移量总是很慢。Postgres必须对所有行进行排序,并将可见行计数到您的偏移量。要直接跳过前面的所有行,您可以将索引的
行号
添加到表中(或创建一个包含所述
行号
),并使用
WHERE row\u number>x
,而不是
OFFSET x

然而,这种方法只适用于只读(或大部分)数据。对于可以同时更改的表数据,实现相同的方法更具挑战性。您需要从准确定义所需的行为开始

我建议对分页使用不同的方法:

SELECT *
FROM   big_table
WHERE  (vote, id) > (vote_x, id_x)  -- ROW values
ORDER  BY vote, id  -- needs to be deterministic
LIMIT  n;
其中
vote_x
id_x
来自上一页的最后一行(对于
DESC
ASC
)。如果向后导航,则从第一个开始

比较行值受已有索引的支持—这是一项符合ISO SQL标准的功能,但并非每个RDBMS都支持它

CREATE INDEX vote_order_asc ON big_table (vote, id);
或按降序排列:

SELECT *
FROM   big_table
WHERE  (vote, id) < (vote_x, id_x)  -- ROW values
ORDER  BY vote DESC, id DESC
LIMIT  n;

这将排除所有id为
的行,这些行是针对SQL Server的,而不是针对PostgresPostgreSQL支持基本的表分区:为什么不使用键集分页@NeilMcGuigan这种方法有一些缺点,例如只有上一页和下一页,但似乎我被迫选择这种方式
SELECT *
FROM   big_table
WHERE  (vote, id) < (vote_x, id_x)  -- ROW values
ORDER  BY vote DESC, id DESC
LIMIT  n;
WHERE  vote >= vote_x
AND    id   > id_x
WHERE (vote = vote_x AND id > id_x) OR vote > vote_x
ORDER  BY vote ASC, id DESC
ORDER  BY vote ASC, (id * -1) ASC