在大表上使用OFFSET优化查询

问题描述 投票:0回答:2

我有桌子

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);

create index vote_order_desc on big_table (vote desc, id desc);

EXPLAIN
显示上面的
SELECT
查询使用了这些索引,但是偏移量很大,无论如何它都非常慢。

如何在大表中优化使用

OFFSET
的查询?也许 PostgreSQL 9.5 甚至更新版本有一些功能?我已经搜索过但没有找到任何东西。

sql postgresql pagination sql-order-by postgresql-9.5
2个回答
39
投票

大的

OFFSET
总是会很慢。 Postgres 必须对所有行进行排序,并将“可见”行计数到您的偏移量。要直接跳过所有前面的行 ,您可以将索引 row_number 添加到表中(或创建一个
MATERIALIZED VIEW
 包括所述 
row_number
)并使用
WHERE row_number > x
而不是
OFFSET x
但是,这种方法仅适用于只读(或大部分)数据。对可以“同时”更改的表数据实施相同的方法更具挑战性。您需要首先

准确地

定义所需的行为。 我建议采用不同的方法: “键集分页”的行值比较

参见:

'WHERE (col1, col2) 的 SQL 语法术语

vote_x
id_x

来自

上一页
的第最后行(对于DESCASC)。或者从
first
(如果导航
向后
)。 (vote, id) 需要是

UNIQUE

才能获得确定性结果。

您已有的索引支持比较行值 - 一个标准 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;

可以使用相同的索引。

我建议您声明您的列
NOT NULL
或熟悉

NULLS FIRST|LAST
结构:


按列 ASC 排序,但先将 NULL 值排序?

ROW

子句中的

WHERE

值不能用单独的成员字段替换。

WHERE (vote, id) > (vote_x, id_x)
 
不能
替换为:
WHERE  vote >= vote_x
AND    id   > id_x
这将排除带有 

id <= id_x
 的所有行,而我们只想针对同一次投票而不是下一次投票这样做。正确的等价物是:

WHERE (vote = vote_x AND id > id_x) OR vote > vote_x

...它不能很好地与索引一起使用,并且对于更多列来说变得越来越复杂。

显然,对于
单列
来说,

会很简单。这就是我一开始提到的特殊情况。

注2 该技术

不适用于

ORDER BY

中的混合方向

,例如: ORDER BY vote ASC, id DESC

如果两列中至少有一列是数字类型,则可以在 

(vote, (id * -1))
 上使用具有倒排值的函数索引 - 并在 
ORDER BY

中使用相同的表达式:

ORDER  BY vote ASC, (id * -1) ASC
相关:

提高多个表中列的排序性能

“以 PostgreSQL 方式完成分页”

  • 您尝试过对表进行分区吗?

-5
投票
易于管理、提高可扩展性和可用性以及 减少阻塞是对表进行分区的常见原因。 提高查询性能并不是使用分区的理由, 尽管在某些情况下它可能是有益的副作用。按照 性能,重要的是确保您的实施计划 包括对查询性能的审查。确认您的索引 表格发布后继续适当支持您的查询 分区,并验证使用集群和 非聚集索引受益于分区消除,其中 适用。

http://sqlperformance.com/2013/09/sql-indexes/partitioning-benefits

© www.soinside.com 2019 - 2024. All rights reserved.