首页 > 数据库 >MySQL在分页查询时的limit深分页问题

MySQL在分页查询时的limit深分页问题

时间:2023-07-19 11:13:16浏览次数:33  
标签:分页 create time 主键 limit MySQL 查询 id

在平时业务中我们会发现当分页数据特别大的时候,会出现SQL很慢的情况,下面我们来分析下为什么会出现这种情况以及如何去解决

一、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_create_time (create_time) //索引
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

当我们进行一下分页查询时

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

SQL的执行流程大致如下:

1、首先通过非族簇索引(idx_create_time ),过滤条件,查询出符合要求数据的主键id。

2、在通过主键Id索引,通过Id主键索引树。找到满足记录的行,然后取出需要展示的列(此过程发生了回表)

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

从以上流程我们就能理解为什么limit深分页问题了。这里主要2个流程导致查询慢

1、发生了回表查询,我们查询的数据越多,那么需要回表查询的次数也就也多。

2、limit 100000,10;在执行时,limit语句会先扫描offset+n行,然后再丢弃掉前offset行,返回后n行数据。也就是说limit 100000,10,就会扫描100010行,而limit 0,10,只扫描10行。

 

二、limit深分页优化方案

我们可以通过减少回表次数来优化,一般有种方法:标签记录法延迟关联法

 1、标签记录法

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

实现方案呢就是记录我们上次查询到的记录id,在这次查询时把id作为查询条件带入

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

这样的话,后面无论翻多少页,性能都会不错的,因为命中了id索引。但是这种方式有局限性:需要一种类似连续自增的字段。

2、延迟关联法

延迟关联法,就是把条件转移到主键索引树,然后减少回表。如下:

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

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

 

标签:分页,create,time,主键,limit,MySQL,查询,id
From: https://www.cnblogs.com/zhuzhen/p/17565006.html

相关文章

  • jdbc-plus是一款基于JdbcTemplate增强工具包,基于JdbcTemplate已实现分页、多租户、动
    ......
  • Mysql基础6-常用数据库函数
    一、字符串函数1、常见Mysql内置字符串函数concat(s1,s2,s3,...):字符串拼接,将s1,s2,s3...等拼接成一个字符串lower(str):将字符串str全部转为小写upper(str):将字符串str全部转为大写lpad(str,n,pad):左填充,将字符串pad对str的左边进行填充,达到n个字符串长度rpad(str,n,......
  • MySQL
    SQLSQL通用语法SQL语句可以单行或多行书写,以分号结尾。SQL语句可以使用空格/缩进来增强语句可读性。MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。注释单行注释:--注释内容或者#注释内容(MySQL特有)多行注释:/*注释内容*/ DDL-数据库操作查询......
  • MySQL高级锁之意向锁
    2.1意向锁2.1.1意向锁的概念意向锁的存在是为了协调行锁和表锁的关系,用于优化InnoDB加锁的策略。意向锁的主要功能就是:避免为了判断表是否存在行锁而去全表扫描。意向锁是由InnoDB在操作数据之前自动加的,不需要用户干预;意向共享锁(IS锁):事务在请求S锁前,要先获得IS锁意向排他锁(IX锁......
  • MySQL高级锁之临键锁
    2.4临键锁2.4.1临键锁的区间测试临键锁(Next-KeyLock):临键锁是查询时InnoDB根据查询的条件而锁定的一个范围,这个范围中包含有间隙锁和记录数;临键锁=间隙锁+记录锁。其设计的目的是为了解决PhantomProblem(幻读);主要是阻塞insert,但由于临键锁中包含有记录锁,因此临键锁所锁定的范......
  • MySQL高级锁之自增锁
    2.5自增锁MySQL的自增锁是指在使用自增主键(AutoIncrement)时,为了保证==唯一性和正确性==,系统会对自增字段进行加锁。这样可以确保同时插入多条记录时,每条记录都能够获得唯一的自增值。创建测试表:droptableifexistst3;CREATETABLE`t3`(`id`int(11)NOTNULLAUTO_INC......
  • PyMySQL插入字典类型的数据
    importpymysqlMYSQL_CONFIG={'host':'localhost',#IP地址'port':3306,#端口'user':'root',#用户名'passwd':'123456',#密码'db':'layui',......
  • Ubuntu安装MySQL、nginx、nacos
    Ubuntu安装mysql1、安装mysql#此命令直接安装最新版mysql8.0sudoapt-getinstallmysql-server2、查看默认用户及密码cat/etc/mysql/debian.cnfuser =debian-sys-maintpassword =s8hjWltF0W2EBU323、登录该用户mysql-udebian-sys-maint-pusemysql;updateuse......
  • mysql text 长度定义
    MySQLText字段长度定义作为一名经验丰富的开发者,我将教你如何实现“MySQLText字段长度定义”。下面我将分步骤向你介绍整个过程,并附上相应的代码示例。步骤步骤说明1创建数据库表2设计Text字段3定义Text字段的长度步骤1:创建数据库表首先,我们需要创建一......
  • mysql 事务自动回滚
    MySQL事务自动回滚在MySQL数据库中,事务是一组原子性操作的集合,它们要么全部成功执行,要么全部失败回滚。事务可以保证在并发环境下数据的一致性和完整性。当一个事务执行出现错误或异常时,数据库会自动回滚到事务开始之前的状态,保证数据的完整性。事务的基本概念在MySQL中,事务由以......