首页 > 数据库 >MySQL Limit 分页查询优化

MySQL Limit 分页查询优化

时间:2024-12-14 17:43:07浏览次数:10  
标签:语句 分页 MySQL 查询 Limit SQL limit 主键

前言

在各类系统的表格类信息展示的功能中,经常会用到“翻页”这个操作,在页面上每次只展示有限的数据,需要看其他数据的时候则像翻书一样翻到后面的“页”。

在 MySQL支持的 SQL 语法中对此有特殊的支持,开发人员在实现这类功能的时候很方便:

  • select * from xxx limit M,N
  • select * from xxx limit N offset M

这两类语法代表的意思是一样的:返回从第 M 开始(不包括这一行)之后的 N 行数据。虽然使用起来很方便,但是这类语句存在查询性能上的陷阱,需要特别注意一下。

原理简介

在解释原理之前,先看一下实际的效果,看看这个“性能的陷阱”是什么。

性能效果图

两个语句的内容都非常简单,差别只在 limit 的部分,第一个语句跳过的行数很少,第二个语句跳过的行数很多,结果是两个语句的执行时间差了至少 200 倍。

PS:limit 配合 order by 使用是一个好习惯,确保结果数据是稳定的

可以看到跳过的行数大幅度增长时,SQL 语句的执行时间也会快速增长,原因其实比较简单:在处理 limit M,N 的时候,MySQL 会先拿到 M+N 行结果数据,然后再丢弃 M 行数据,展示之后剩下的 N 行数据。

所以上图的第二个语句实际上扫描了 800 多万行数据,然后丢弃了 800 万行数据,只展示之后的 1 行结果。

explain 和 optimizer_trace 都看不出来差别,但是 profile 里面能看出来两者的差距:

profile 结果

虽然都只输出一行结果,但是在 Sending data 阶段花费的时间差别很大,其实就是花在扫描 800 万行数据上去了。

优化策略

针对这个问题,其实有一个比较通用的优化思路:利用 join,先根据主键搜索到需要的数据,再通过主键关联到原来的表输出结果。

SQL 可以改写一下:

SQL 改写的效果

可以看到查询时间降到了 1.5s 左右,提升了约 37%,看起来还可以,那么还有其他的办法么?

显然还是有的,不过这会要求表有自增主键。

在分页查询的时候,记录上一次查询结果中的主键,然后在 where 条件中添加主键的范围约束

以上面的查询为例,上次分页查询时的主键是 8000001,那么下次分页的时候,where 条件中添加一个主键约束:id > 8000001,再来看看查询效果:

添加条件之后的效果

可以发现利用主键来筛选掉上一次分页前的所有数据后再用 limit,查询基本是马上返回结果的。

不过要特别注意,这种方法是根据主键的顺序先做了一次筛选,不一定会适用于所有的业务场景,理论上 UUID 类的主键也可以用,但是改造 SQL 前务必确保查询结果是符合预期的

总结一下

MySQL 由于本身查询优化器覆盖到的场景不够全,慢查询的原因也千奇百怪,各类业务 SQL 在上线前尽量多覆盖一些场景,确保业务功能安全发布。

标签:语句,分页,MySQL,查询,Limit,SQL,limit,主键
From: https://www.cnblogs.com/shujuyr/p/18449791

相关文章

  • Python爬取数据插入mysql(简易记录)
    importmysql.connectorimportrequestsfromlxmlimporthtml#连接MySQL数据库db=mysql.connector.connect(host="?",user="?",password="?",database="?")cursor=db.cursor()company_url=......
  • mysql-搭建主从复制
    mysql-搭建主从复制Master(主):dockerrun-p3339:3306--namemaster-eMYSQL_ROOT_PASSWORD=123456-dmysql:5.7Slave(从):dockerrun-p3340:3306--nameslave-eMYSQL_ROOT_PASSWORD=123456-dmysql:5.7Master对外映射的端口是3339,Slave对外映射的端口是3340。因为do......
  • vxe-table 实现复选框分页跨页勾选
    vxe-table实现复选框分页跨页勾选官网:https://vxetable.cn当使用数据分页与复选框多页勾选时,可以通过checkbox-config.reserve启用<template><div><vxe-buttonstatus="success"@click="getSelectEvent">获取已选</vxe-button><vxe-grid......
  • 免费送源码:Java+ssm+MySQL SSM智慧旅游系统 计算机毕业设计原创定制
     摘要随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。智慧旅游系统设计,主要的模块包括查看首页、站点内容(轮播图、公告栏)系统用户(管理员、注册用户、导游)公共内容(旅游资讯、资讯分类)模块管理(地区管理、景点信息......
  • 免费送源码:Java+B/S+MySQL 多元化智能选课系统的设计与实现 计算机毕业设计原创定制
    摘 要多元化智能选课系统使用Java语言的Springboot框架,采用MVVM模式进行开发,数据方面主要采用的是微软的Mysql关系型数据库来作为数据存储媒介,配合前台技术完成系统的开发。论文主要论述了如何使用JAVA语言开发一个多元化智能选课系统,本系统将严格按照软件开发流程进行各个......
  • MySQL 事务
     概念介绍         事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们达到这样的效果。        事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假......
  • Mac安装mysql8.0版本数据库
    一、环境和所需软件概述1.1目前环境:MacOS(10.15.3)1.2所需软件:mysql-8.0.18-macos10.15-x86_64.dmg(8.0系列都可以)二、安装步骤(全部采用高清大图吧!!)2.1进入mysql安装包下载页面,下版本的dmg文件,下载地址如下:msyql官网下载地址-------------图一-----------------......
  • Linux安装MySQL8.0
    在linux系统的下切换到/usr/local目录下创建mysql文件夹,也可以自定义文件夹。#切换目录cd/usr/local#创建文件夹mkdirmysql切换到刚创建的目录下,并使用wget下载mysql压缩包。我们选择MySQL8.0.20cdmysqlwgethttps://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8......
  • Windows安装MySQL8.0
    一、下载MySQL安装包MySQL直接去官网下载就行,选择community版本(免费)下载,链接:https://dev.mysql.com/downloads/mysql/。在“MySQLCommunityServer”页面,根据您的Windows系统版本(32位或64位)选择合适的安装包进行下载。一般来说,现在大多数电脑都是64位系统,我们以6......
  • 【linux下mysql主从复制操作流程】
    linux下mysql主从复制操作流程在Linux下实现MySQL主从复制(Master-SlaveReplication)是一个常见的需求,用于读写分离、数据备份等场景。以下是一个详细的操作流程,包括每个步骤、注意事项以及总结。一、准备环境安装MySQL确保主服务器(Master)和从服务器(Slave)都已经安装了My......