当前位置:  开发笔记 > 数据库 > 正文

在大表上使用OFFSET优化查询

如何解决《在大表上使用OFFSET优化查询》经验,为你挑选了1个好方法。

我有桌子

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甚至更新版本都有一些功能?我搜索过但没找到任何东西.



1> Erwin Brands..:

一个大OFFSET的总是很慢.Postgres必须订购所有行并计算可见的行数到您的偏移量.要直接跳过所有以前的行,您可以添加索引row_number到表(或创建MATERIALIZED VIEW包含说row_number)并使用WHERE row_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_xid_x来自最后的排前一页(对于DESCASC).或者从第一个向后导航.

您已经拥有的索引支持比较行值 - 这是一个符合ANSI 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构造:

PostgreSQL按日期时间asc排序,先是null吗?

特别注意两件事:

    子句中的ROWWHERE不能用分隔的成员字段替换.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
    

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

    显然,对于单个列来说很简单.这是我在一开始就提到的特殊情况.

    该技术不适用于混合方向,ORDER BY如:

    ORDER  BY vote ASC, id DESC
    

    至少我想不出一种有效实现这一点的通用方法.如果两列中的至少一列是数字类型,则可以使用具有反转值的功能索引(vote, (id * -1))- 并在以下表达式中使用相同的表达式ORDER BY:

    ORDER  BY vote ASC, (id * -1) ASC
    

有关:

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

使用许多表中的列提高订单的性能

请特别注意Markus Winand的演讲,我将其链接到:

"Pagination做了PostgreSQL的方式"

推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有