MySQL深分页,limit 100000,10 优化

文章目录

  • 一、limit深分页为什么会变慢
  • 二、优化方案
    • 2.1 通过子查询优化(覆盖索引)
      • 回顾B+树结构
      • 覆盖索引
      • 把条件转移到主键索引树
    • 2.2 INNER JOIN 延迟关联
    • 2.3 标签记录法(要求id是有序的)
    • 2.4 使用between...and...

我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分4个方案,讨论如何优化MySQL百万数据的深分页问题.

参考 实战!聊聊如何解决MySQL深分页问题

一、limit深分页为什么会变慢

表结构

CREATE TABLE account (id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',name varchar(255) DEFAULT NULL COMMENT '账户名',balance int(11) DEFAULT NULL COMMENT '余额',create_time datetime NOT NULL COMMENT '创建时间',update_time datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (id),KEY idx_name (name),KEY idx_update_time (update_time) //索引
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

执行的深分页SQL为

select id,name,balance from account where update_time> '2020-09-19' limit 100000,10;

这个SQL的执行时间如下:

img

执行完需要0.742秒,深分页为什么会变慢呢?如果换成 limit 0,10,只需要0.006秒哦

img

我们先来看下这个SQL的执行流程

  1. 通过普通二级索引树idx_update_time,过滤update_time条件,找到满足条件的记录ID。

  2. 通过ID,回到主键索引树,找到满足记录的行,然后取出展示的列(回表

  3. 扫描满足条件的100010行,然后扔掉前100000行,返回。

    (每一条select语句都会从1遍历至当前位置,若跳转到第10000页,则会遍历100000条记录)

在这里插入图片描述

执行计划如下: img

SQL变慢原因有两个

  1. limit语句会先扫描offset+n行,然后再丢弃掉前offset行,返回后n行数据。也就是说limit 100000,10,就会扫描100010行,而limit 0,10,只扫描10行。
  2. limit 100000,10 扫描更多的行数,也意味着回表更多的次数。

二、优化方案

2.1 通过子查询优化(覆盖索引)

因为以上的SQL,回表了100010次,实际上,我们只需要10条数据,也就是我们只需要10次回表其实就够了。因此,我们可以通过减少回表次数来优化。

回顾B+树结构

如何减少回表次数呢?我们先来复习下B+树索引结构

InnoDB中,索引分主键索引(聚簇索引)和二级索引

  • 主键索引,叶子节点存放的是整行数据
  • 二级索引,叶子节点存放的是主键的值

img

覆盖索引

覆盖索引(covering index ,或称为索引覆盖)即从非主键索引中就能查到的记录,而不需要查询主键索引中的记录,避免了回表的产生减少了树的搜索次数,显著提升性能。

如何确定数据库成功使用了覆盖索引呢? —— 当发起一个索引覆盖查询时,在explain的extra列可以看到using index的信息

在这里插入图片描述

可以看到Extra中的Using index,表明我们成功使用了覆盖索引

把条件转移到主键索引树

如果我们把查询条件,转移回到主键索引树,那就不就可以减少回表次数啦。转移到主键索引树查询的话,查询条件得改为主键id了,之前SQL的update_time这些条件咋办呢?抽到子查询那里嘛~

子查询那里怎么抽的呢?因为二级索引叶子节点是有主键ID的,所以我们直接根据update_time来查主键ID即可,同时我们把 limit 100000的条件,也转移到子查询,完整SQL如下:

select id,name,balance FROM account where id >= (select a.id from account a where a.update_time >= '2020-09-19' limit 100000, 1) LIMIT 10; -- (可以加下时间条件到外面的主查询)

查询效果一样的,执行时间只需要0.038秒! 0.742秒 ——> 0.038秒

img

我们来看下执行计划 img

由执行计划得知,子查询 table a查询是用到了idx_update_time索引。首先在索引上拿到了聚集索引的主键ID,省去了回表操作,然后第二查询直接根据第一个查询的ID往后再去查10个就可以了!

img

所谓的覆盖索引就是从普通索引树中就能查到的想要数据,而不需要通过回表从主键索引中查询其他列,能够显著提升性能。

因此,这个方案是可以的~

2.2 INNER JOIN 延迟关联

延迟关联的优化思路,跟子查询的优化思路其实是一样的:都是把条件转移到主键索引树,然后减少回表。不同点是,延迟关联使用了inner join代替子查询。

优化后的SQL如下:

SELECT  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.update_time >= '2020-09-19' ORDER BY a.update_time LIMIT 100000, 10) AS  acct2 on acct1.id= acct2.id;

查询效果也是杠杆的,只需要0.034秒

img

执行计划如下:

img

查询思路就是,先通过idx_update_time二级索引树查询到满足条件的主键ID,再与原表通过主键ID内连接,这样后面直接走了主键索引了,同时也减少了回表。

2.3 标签记录法(要求id是有序的)

limit 深分页问题的本质原因就是:偏移量(offset)越大,mysql就会扫描越多的行,然后再抛弃掉。这样就导致查询性能的下降

其实我们可以采用标签记录法,就是标记一下上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描。就好像看书一样,上次看到哪里了,你就折叠一下或者夹个书签,下次来看的时候,直接就翻到啦

select id,name,balance from account limit 1000000,10;

假设上一次记录到100000,则SQL可以优化为:

select id,name,balance FROM account where id > 100000 order by id limit 10;

这样的话,后面无论翻多少页,性能都会不错的,因为命中了id索引。但是你,这种方式有局限性:要求id连续的、并且有序

在有序的条件下,也可以使用比如创建时间等其他字段来代替主键id,但是前提是这个字段是建立了索引的。

id不是连续,我们可以通过order by让它连续

总之,使用条件过滤的方式来优化 limit 是有诸多限制的,一般还是推荐使用覆盖索引的方式来优化。

2.4 使用between…and…

很多时候,可以将limit查询转换为已知位置的查询,这样MySQL通过范围扫描between...and,就能获得到对应的结果。

select id,name,balance from account limit 1000000,10;

如果知道边界值为100000,100010后,就可以这样优化:

select id,name,balance FROM account where id between 100000 and 100010 order by id desc;

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

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

相关文章

引擎:UI

一、控件介绍 Button 按钮 创建一个按钮 按钮禁用 精灵模式 颜色模式 缩放模式 绑定点击事件 EditBox 输入框 Layout 布局 支持水平排列、垂直排列、背包排列 PageView 页面视图 ProgressBar 进度条 RichText 富文本 绑定点击事件 事件可以被其它标签包裹 图文混排 Scroll…

AG32 MCU+FPGA 使用感受

前言: 笔者35了,10多年前开始玩单片机/FPGA啥的,从现在回想过去,眼下真的是我们国家微电子发展的好时候。各种各样的国产单片机,FPGA啥的,想想本科的时候用的Freescale,后来用的STM32&#xff0…

UI 自动化中的分层设计

以前的设计 在过去 UI 自动化测试领域有一个规范的设计模式是 page object 模式。 意思是测试用例不会直接定位页面元素, 而是把每一个页面封装成一个类。 在这个类中封装页面元素。 然后测试用例调用 page 类来操作页面元素完成测试用例。如下图: 以前…

【工具变量】巡回法庭DID数据(2000-2022)(附部分stata代码)

数据来源: 时间跨度:2000-2022 数据范围:全国 数据指标: 参考刘中华和黄斯琪等学者的做法,将当年企业总部所在省份被巡回法庭覆盖赋值为1,否则为0。数据提供两个版本excel版本和dta版本,还附…

【Emgu CV教程】10.14、ConnectedComponents()函数计算连通区域

文章目录 一、概念1.什么叫图像的连通区域2.提取连通区域的函数 二、简单应用1.原始素材2.代码3.运行结果4.连通区域上色 一、概念 1.什么叫图像的连通区域 图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找出彼此互…

云工场上市在即:资产负债比率飙升,巨额分红3000万远超净利润

《港湾商业观察》施子夫 今年5月底,冲刺港交所上市的云工场科技控股有限公司(以下简称,云工场)通过聆讯。 6月5日,云工场宣布将于2024年6月5日至6月11日进行招股,预计在6月14日上市。公司计划发售1.15亿股…

【UE5.1 角色练习】11-坐骑——Part1(控制大象移动)

前言 在上一篇(【UE5.1 角色练习】10-物体抬升、抛出技能 - part2)基础上创建一个新的大象坐骑角色,并实现控制该角色行走的功能。 效果 步骤 1. 在商城中下载“African Animal Pack”资产和“ANIMAL VARIETY PACK”资产导入工程中 2. 复…

【deepin 邀您体验】玲珑 10 分钟快速构建指南!

玲珑 作为一种新型的独立包管理工具集,玲珑主要提供分层与隔离的运行环境,解决传统包管理系统强依赖导致的兼容性问题,以及权限松散导致的安全问题。当前,玲珑已支持 4 个发行版,包括 deepin、统信 UOS 以及 Debian 和…

golang 中的复合类型

前言 所有的api文档都可以使用bash命令 go doc 查看文档的帮助信息 从 Go 1.13 开始,godoc 不再随 Go 发行版一起安装,你需要单独安装它。 需要单独安装 1. go install golang.org/x/tools/cmd/godoclatest 2执行命令 godoc -http:1111 打开浏览器 http:…

java之基础2笔记

1 类型转换 1.1 自动类型转换(隐式类型转换) 从小的数据类型到大的数据类型的转换(如 int 到 long)。 从低精度的数据类型到高精度的数据类型的转换(如 float 到 double)。 1.2 强制类型转换&#xff0…

儿童护眼灯哪个好?带你了解适合儿童的护眼灯款式分享

儿童护眼灯哪个好?作为我们日常生活中极为实用的小家电,为了确保使用台灯时的舒适性并且保护视力,选择一款专业的护眼台灯成为了一个明智的决定。这样的台灯能够提供更舒适、均匀的照明环境,那么到底儿童护眼灯哪个好你&#xff1…

实现手机空号过滤或手机号码有效性验证

手机空号过滤或手机号码有效性验证通常涉及使用专门的API接口来查询手机号码的状态。这些API接口通常由第三方服务提供商提供,它们会与电信运营商合作或利用自己的数据库来验证手机号码是否真实存在、是否已被分配、是否处于空号状态等。 以下是一些步骤和考虑因素…

爬虫——有道云翻译

废话不多说直接上代码 固定文本内容 import timefrom selenium import webdriver from selenium.common.exceptions import NoSuchElementException, TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWai…

Day 41 NGINX详解

Nginx详解 一、HTTP协议 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。 1、HTTP 工作原理 HTTP协议通信流程 WEB Server&…

超维小课堂 | 6、MAVROS与机载电脑Jetson nano通信

MAVROS与机载电脑Jetson nano通信 ROS系统镜像——Jetson nano b01 4G 链接: 百度云镜像链接 链接:https://pan.baidu.com/s/1NoIEvVdsiYLPvVOWM98hjQ 提取码:cwkj 简介:MAVROS和Jetson nano通信,设置飞控参数和MAVROS文件&am…

程序猿大战Python——了解Python

了解Python 编程语言的发展 目标:了解编程语言。 我们知道,咱们的日常沟通交流使用的语言:普通话。 那什么是编程语言呢? 【官方解释】编程语言是用来定义程序的语言形式,也就是说,我们可以通过编程语言…

root账号,cmd命令行能用ssh连上服务器,但是vscode连接报错Permission denied,please try again

☆ 问题描述 但是cmd能连接上 ★ 解决方案 点击 然后add到自己的配置文件下 重新选择 这个时候就会出现刚刚添加的,点击选择 输入密码 然后就ok了 ✅ 总结 只能说:玄学!

剪画小程序:自媒体必备神器:【视频翻译】自动识别语言、翻译、配音,让外语视频秒变母语!

Hello,大家好呀!我是不会画画的小画~ 今天给大家带来一款敲实用的视频翻译工具一一 小程序【剪画】 我们有很小伙伴在学习他国语言时,最大的障碍就是语言的问题了,想要 理解其中的内容,在这之前要下很大的功夫去掌握…

创业新风口:智能售货机的崛起

随着科技的飞速发展,智能售货机已经不再是简单的自动贩卖机,它们变得更加智能、灵活,能够适应各种场景需求,从传统的饮料、零食到新鲜水果、便当、甚至是电子产品,无所不包。这种24小时无人值守的商业模式,…

居民社区团购小程序源码系统 拼团管理+团长管理功能 带完整的安装代拿代码包以及搭建教程

系统概述 居民社区团购小程序源码系统是一款专为社区团购打造的一站式解决方案。它整合了拼团管理和团长管理等核心功能,能够帮助企业和创业者快速搭建自己的社区团购平台,实现高效运营和便捷管理。 代码示例 系统特色功能 1.拼团管理:支持…