postgresql之翻页优化

news2024/11/16 7:49:44

列表和翻页是所有应用系统里面必不可少的需求,但是当深度翻页的时候,越深越慢。下面是几种常用方式

准备工作

CREATE UNLOGGED TABLE data (
   id bigint GENERATED ALWAYS AS IDENTITY,
   value double precision NOT NULL,
   created timestamp with time zone NOT NULL
);

/* 设置随机数种子 */
SELECT setseed(0.2740184);
/* 初始化数据 */
INSERT INTO data (value, created)
SELECT random() * 1000, d
FROM generate_series(
        TIMESTAMP '2022-01-01 00:00:00 UTC',
        TIMESTAMP '2022-12-31 00:00:00 UTC',
        INTERVAL '1 second'
     ) AS d(d);

/* 添加主键 */
ALTER TABLE data ADD PRIMARY KEY (id);

/* 回收空间,并对表数据进行统计分析 */
VACUUM (ANALYZE) data;

我们的查询目标是下面的SQL

SELECT value, created
FROM data
WHERE value BETWEEN 0 AND 10
ORDER BY created;

为了加速查询我们可以创建对应索引

CREATE INDEX data_created_value_idx ON data
   (created, value);

简单分页 LIMIT ? OFFSET ?

这是第一种方式

-- 首页
SELECT value, created
FROM data
WHERE value BETWEEN 0 AND 10
ORDER BY created
LIMIT 50;
-- 第 深n 页
SELECT value, created
FROM data
WHERE value BETWEEN 0 AND 10
ORDER BY created
OFFSET 180000 LIMIT 50;

不论是mysql 还是pg数据库 直接使用offset limit 这种查询的时候都是扫描处理前 n * pageSIze 数据然后丢弃前面 (n-1) * pageSize页的数据,数据库是否使用索引是有优化策略的,当经过一系列复杂的预估之后,假如数据库优化器 判定 走索引还没全表扫描效率高的时候就会放弃走索引,这个时候我们的查询就会比较慢,基本上都是秒级别的了
上面两个sql的执行计划如下
在这里插入图片描述
在这里插入图片描述
全表扫描最大的问题不仅仅是某个查询慢,更严重的是会导致锁表

缺点

  • 页码越深,性能越差,但是假如用户只关心前面几页的数据,是没有什么问题的
  • 并发情况下翻页会有跳数据或者重复数据的问题,比如用户A是在查看数据翻页的,用户B在第一页加了一条数据,这个时候用户A翻页,那么原来第一页最后的数据就会被挤到第二页,类似这种情况,但是一般的时候非高并发情况可以不考虑

优点

简单,不管怎么翻都一招鲜 吃遍天

使用游标 WITH HOLD CURSORS

WITH HOLD CURSORS是一种特殊的游标,与普通游标主要区别如下

  • 普通游标:普通游标(或称为会话级游标)的生命周期通常与创建它的事务相同。这意味着,当事务提交或回滚时,游标也会被关闭,其相关的资源会被释放。
  • WITH HOLD CURSORS:WITH HOLD游标在事务结束后仍然保持打开状态,即使原始事务已经提交或回滚。这使得游标可以在多个事务之间保持活动状态,直到显式关闭或会话结束
    但是在分页情况下我们一般一页是一个请求,这个时候肯定是不同的事务,所以这个时候普通游标是无法满足我们的要求的
    我们使用WITH HOLD CURSORS
DECLARE c SCROLL CURSOR WITH HOLD FOR
SELECT value, created
FROM data
WHERE value BETWEEN 0 AND 10
ORDER BY created;

在这里插入图片描述
获取任意数据

-- 移动游标
MOVE ABSOLUTE 4950 IN c;
-- 获取数据
FETCH 50 FROM c;

注意继续FETCH会继续后翻页
在这里插入图片描述
还需要注意的是这个游标用完可一定要关闭、关闭;关闭,重要的事情说三遍

-- 关闭游标
CLOSE c;

优点

  • 适用于所有查询,不管是第一页还是最后一页,效率一样
  • 结果集是稳定的,没有像OFFSET和LIMIT那样跳过或重复结果
  • 可以跳页,从第5页,直接跳到第100页

缺点

  • 当完成操作时,一定不要忘记关闭游标,否则结果集将保存在服务器上,直到数据库会话结束
  • 如果游标长时间打开,数据将变的陈旧,无法获取动态的最新数据
  • 游标长时间打开,相当于一个长事务

KEYSET PAGINATION

暂时翻译为位点,原理上就是记录上一次数据最后一条内容,所以,这个值必须是唯一的强有序的,这样翻页的时候才不会重复或者跳过数据

-- 首页查询
SELECT id, value, created
FROM data
WHERE value BETWEEN 0 AND 10
ORDER BY created, id
LIMIT 50;

-- 基于上面位点的下一页
SELECT id, value, created
FROM data
WHERE value BETWEEN 0 AND 10
  AND (created, id) > ('2022-01-01 01:27:35+01', 5256)
ORDER BY created, id
LIMIT 50;

在这里插入图片描述
位点查询
在这里插入图片描述
如果使用这种方式的话我们添加这个索引效率会更好

CREATE INDEX data_keyset_idx ON data
   (created, id, value);

优点

  • 每次查询只获取我们需要的数据,不需要扫描不额外的数据,减少了相关资源代价
  • 每个查询将展示最新并发数据修改的当前数据

缺点:

  • 需要一个专门为查询而设计的特殊索引
  • 需要对业务进行改造只有事先能获取到确切的位点,查询时才有用,并且当我们修改排序字段或者条件的时候,这个位点可能跟之前的就不一致了。
  • 前后端都需要改造

其他

一般情况下我们可能也需要count这个值,上面三种方式中WITH HOLD CURSORS是天然支持的

MOVE ALL IN c;

在这里插入图片描述
剩下两种都是扫描全表,使用昂贵的资源,简单点跟产品battle 不支持,tips:对于ES深度翻页,直接limit比PG,MySQL资源更严重,因为ES会在每个分区上进行计算到协作节点进行统一聚合,所以一般的ES可能会关闭这种深度分页或者使用游标,类似Feed流,下一个下一个。整体思想是一致的。

参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1800359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI大模型日报#0607:10家国产大模型、GPT-4o挑战高考作文 | OpenAI公开破解GPT-4新方法

导读:AI大模型日报,爬虫LLM自动生成,一文览尽每日AI大模型要点资讯!目前采用“文心一言”(ERNIE 4.0)、“零一万物”(Yi-Large)生成了今日要点以及每条资讯的摘要。欢迎阅读&#xf…

新媒体暴力起号必备因素!沈阳新媒体运营培训学校

1周涨粉10w?这对普通人来说可以说是天文数字,但只要掌握方式方法,普通人也能做到! 面试经验丰富的人都深知,给面试官留下的第一印象相当重要,几乎决定了80%的面试机会。标题也是如此,在完成一篇…

【c语言】指针就该这么学(3)

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:C语言 目录 一、函数指针 1.函数指针变量的创建 2.函数指针变量的使用 二、typedef关键字 三、函数指针数组 1.函数指针数组的概念 2.函数指针数…

SD卡格式化怎么恢复?一键扫描,轻松找回丢失的数据

SD卡格式化怎么恢复数据?在日常生活中,我们常常会使用SD卡来存储各种数据,如照片、视频、文档等。然而,当SD卡意外格式化或者出现其他问题时,里面的数据就会面临丢失的风险。 此时,如何恢复格式化的SD卡就…

webgl_clipping_stencil

ThreeJS 官方案例学习&#xff08;webgl_clipping_stencil&#xff09; 1.效果图 2.源码 <template><div><div id"container"></div></div> </template> <script> import * as THREE from three; // 导入控制器 import …

成都跃享未来教育咨询有限公司,值得信赖!

在浩渺的教育咨询市场中&#xff0c;成都跃享未来教育咨询有限公司以其独特的魅力和卓越的服务质量&#xff0c;成为了行业内的璀璨明星。作为一家致力于为学生提供全方位教育咨询服务的公司&#xff0c;成都跃享未来教育咨询有限公司始终坚持安全可靠的原则&#xff0c;为广大…

docker命令 docker ps -l (latest)命令在 Docker 中用于列出最近一次创建的容器

文章目录 12345 1 docker ps -l 命令在 Docker 中用于列出最近一次创建的容器。具体来说&#xff1a; docker ps&#xff1a;这个命令用于列出当前正在运行的容器。-l 或 --latest&#xff1a;这个选项告诉 docker ps 命令只显示最近一次创建的容器&#xff0c;不论该容器当前…

SAP ERP系统主要模块简介

SAP系统通过提供一系列高度灵活的模块&#xff0c;满足企业在不同业务领域的需求。这些模块不仅功能齐全且相对独立&#xff0c;但它们之间又能紧密协作&#xff0c;共同构筑一个协同高效的工作环境。 财务会计&#xff08;FI&#xff09;模块 它涵盖了总账、应收账款、应付账…

fs.1.10 ON rockylinux8 docker镜像制作

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 rockylinux docker上编译安装fs1.10版本的流程记录。 环境 docker engine&#xff1a;Version 24.0.6 rockylinux docker&#xff1a;8 freeswitch&#xff1a;v1.10.7 手动模式 rockylinux准备 docker hub拉取r…

第三篇——大数据思维的科学基础

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 大数据时代&#xff0c;大数据思维的重要性不言而喻&#xff1b;而信息在…

搜索引擎优化服务如何寻找?

首先你要了解搜索引擎优化&#xff0c;也就是seo具体是什么&#xff0c;要做些什么&#xff0c;然后就是确定你自身业务的需求&#xff0c;是要特定的关键词排名&#xff0c;还是整体网站流量的提升&#xff0c;还是想要优化目前的网站 接下来你就可以正式的寻找真正能帮助到你…

three.js官方案例(animation / multiple)webgl_animation_multiple.html学习笔记

目录 ​编辑 1 骨架工具&#xff08;SkeletonUtils&#xff09; 1.1 clone方法 2 蒙皮网格&#xff08;SkinnedMesh&#xff09; 3 自测 4 webgl_animation_multiple.html全部脚本 1 骨架工具&#xff08;SkeletonUtils&#xff09; 用于操控 Skeleton、 SkinnedMesh、和…

springboot项目部署需要redis集群问题

本来直接将redis为单独启动模式转为配置 yml文件 spring.redis.cluster.nodes: 192.168.12.78:8001,192.168.12.78:8002,192.168.12.78:8003, java文件 package io.sirc.config;import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.ann…

【JSP】如何在IDEA上部署JSP WEB开发项目

以我的课设为例&#xff0c;教大家拿到他人的项目后&#xff0c;如何在IDEA上部署。 需要准备&#xff1a; JDK17&#xff08;或者JDK13&#xff09;IntelliJ IDEA 2023.2.6MySQL 8.0Tomcat 9.0 一&#xff0c;新建项目添加文件 1.1复制“位置”的路径 1.2找到该文件夹 1.3…

SQLite3(1):介绍安装与测试

目录 1、SQLite3介绍 2、SQLite3的优势和特性 3、SQLite3安装与测试 3.1 SQLite3安装 3.2 SQLite3测试 4、SQLite3简单使用 4.1 连接数据库文件 4.2 创建信息表 4.3 插入三个学生信息 4.4 确认信息 5、总结 1、SQLite3介绍 SQLite3是一种轻量级的关系型数据库管理系…

kafka集群内外网分流方案——筑梦之路

前言 在现代分布式系统架构中&#xff0c;Kafka作为一款高性能的消息队列系统&#xff0c;广泛应用于大数据处理、实时流处理以及微服务间的异步通信场景。特别是往往企业级应用中&#xff0c;业务网段和内网通信网段不是同一个网段&#xff0c;内网的机器想要访问业务数据只能…

计网复习资料

一、选择题&#xff08;每题2分&#xff0c;共40分&#xff09; 1. Internet 网络本质上属于&#xff08; &#xff09;网络。 A.电路交换 B.报文交换 C.分组交换 D.虚电路 2.在 OSI 参考模型中,自下而上第一个提供端到端服务的是( )。 A.数据链路层 B.传输…

【YOLOv10】使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!

NVIDIA TensorRT ™ 是一款用于高性能深度学习推理的 SDK&#xff0c;包含深度学习推理优化器和运行时&#xff0c;可为推理应用程序提供低延迟和高吞吐量。YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法&#xff0c;通过消除NMS、优化模型架构和引入创新模块等策…

C++进阶之二叉搜索树

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 C进阶​ ​​​​算法 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.二叉搜索树概念 二.实现 2.1插入 …

K8s存储对象的使用

背景和概念 容器中的文件在磁盘上是临时存放的&#xff0c;这给在容器中运行较重要的应用带来一些问题&#xff1a; 当容器崩溃或停止时&#xff0c;此时容器状态未保存&#xff0c; 因此在容器生命周期内创建或修改的所有文件都将丢失。另外 在崩溃期间&#xff0c;kubelet 会…