limit 10和limit 10000 10效率相同吗

先说结论:不相同,差异很大。

set profiling = 1;

select * from xiatui order by id limit 10000,10;

select * from xiatui order by id limit 10;

show profiles;

select * from xiatui order by name limit 90000,10;

select * from xiatui order by name limit 10;

对比Query_ID为57和64的语句发现执行时间limit 10比limit 10000,10效率高了10倍。什么原因呢?这就要从limit的底层原理开始讲起。请继续往下看。

分页查询和深度分页的问题

select * from page order by id limit offset, size;

分页查询经常会遇到,在查找网站的时候肯定遇到分页的信息,比如百度信息,查找到的信息会分为很多页展示给用户,而不是一股脑的放在一个页展示给用户(一股脑的展示会导致查询全部表信息,效率特别慢,为了解决这种情况才发明了分页查询,但是分页查询会导致深度分页,什么是深度分页呢?往下看)。

大家仔细观察上面这张图,百度解决深度分页查询的方式就在其中。

分页查询语句的解释

上述语句的意思

如果我们前端规定一个页有10条数据,下面的语句就是查询第一页的全部数据。

select * from xiatui order by id limit 10;

一个页有十个数据,第10页就是从第90行取十个数据。 

select * from xiatui order by id limit 90,10;

那limit 10000,10就是第1001页。

limit  10000,10和limit  10的执行过程

还是上面的问题limit  10000,10和limit 10为什么查询效率不同?

limit 10的执行过程

limit  10就相当与limit  0

主键索引的limit执行过程

limit  10

explain
select * from xiatui order by id limit 10;

 可以看到执行计划:主键索引,rows=10,说明这条语句走了主键索引,并且只扫描了10行数据,可想而知就是前十条数据。

具体流程:server层调用存储引擎层innodb接口,在innodb的主键索引获取第0行完整数据返回给server层,放到server层的结果集,之后继续调用接口,获取主键索引的第1行数据返回,依次获取10条数据,放到结果集,返回给客户端。

limit  10000,10

explain
select * from xiatui order by id limit 10000,10;

 可以看到执行计划:主键索引,rows=10010,说明走了主键索引,扫描了10010行数据。这是为什么呢,我们只要第10000开始的十条数据,为什么扫描这么多行,这就是mysql优化器存在的缺陷,想要获取第10000行数据,只能从头开始扫描,直到扫描到第10000行数据。

  有的人脑子转的快就会想,为什么不通过索引直接找到值为10000的数据?

   nonono,这就理解错了,第10000行数据和id为10000是有很大区别的,这两个概念千万别混淆,索然说可能你设置了主键自增,从0开始可能都对上了,但是删除元素呢,况且并不是所有情况都是主键自增。所以mysql只能通过从头扫到想要开始的行(这期间维护了一个count值,扫描下一个就增加1,直到count=想要找到的行)

集体流程:server层调用innodb接口,和上面一样的流程,不一样的就是会在主键索引中依次获得第0行到第10010行的完整记录,依次返回给server层,由server层根据offset值挨个过滤,只留下符合条件的数据,依次放到结果集,返回给客户端。

问题解答

看完基于主键索引的limit可以回答上面的问题,为什么limit 10000,10比limit 10慢?

是因为limit  10000,10会取出10010条数据,由server过滤丢弃10000条记录,这部分消耗很大。

优化方法

那关于limit 10000,10效率慢有什么方法进行优化呢?

我们可以将上面语句改成

select * from xiatui x inner join
(select id from xiatui order by id limit 10000,10) c
on x.id = c.id;

或者

select * from xiatui where id > (select id from xiatui order by id limit 90000,1) order by id limit 10;

可以看到执行时间相对于原语句变快了很多。

上述两条语句的解决方法原理就是利用我上面提到过的问题:为什么不通过索引直接找到值为10000的数据?原因已经在上面做出解答,这两个语句就是利用索引去主键索引中定位到开始数据的行。

子查询语句中的子查询就是找到第90000行数据,有些人就会有疑问这不也得依次从头找到第90000行吗,没错子查询确实是从第0行找到90000行,但是和select *有区别的是select id,这样直接就可以index扫描索引树,取到id值就直接返回数据给server层(而不用返回所有的数据),由server进行过滤,返回的数据量大大减少。

表连接的意思就是先获取结果集的id值生成派生表,之后和原表进行id的关联,这样就可以获取所属id的数据,返回数据给server层。

基于非主键索引的limit执行过程

limit  10

explain
select * from xiatui order by name limit 10;

执行过程:server层调用innodb端口,辅助索引name中获取第0条数据返回主键id,回表找到完整的行数据,返回给server层,放到结果集中,之后依次取10条。

当offset > 0,且offset的值较小的时候,也是这个流程,区别就是会丢弃offset之前的数据。

explain
select * from xiatui order by name limit 100,10;

 非主键索引的limit过程比主键索引的limit过程,多了徽标的消耗。

limit  10000,10

当offset变得非常大时,执行计划变成全表扫描。

这和上面的有所不同,全表扫描,rows=93903,这就是表中的全部数据,为什么要扫描全部的数据,而不是从头扫到需要的数据行?

nonono,这也是个误区,既然走了全表扫描,order by name,说明语句需要根据name列进行排序,如果没有走name的辅助索引,而是全表扫描主键索引,主键索引不是的name不是有序的,所以就需要扫描全部数据,应用filesort文件进行排序,所以这是它rows=count(*)的原因。而这个原因也就是order by id 和 order by name的区别。

根据上面说的当offset过大的时候会造成效率很低。

优化方法

select * from xiatui x inner join
(select id from xiatui order by name limit 90000,10) c
on x.id = c.id;

可以看到优化过后的语句效率有显著的提升。

仔细分析上面的优化语句,在何种方面进行了优化?没错避免了回表,注意是避免而不是减少。我们来分析下执行过程:辅助索引依次返回90010条数据,不用回表直接返回给server层,再由server层进行把90000前的数据过滤掉。

总结

不管是基于主键索引还是基于非主键索引,都不能避免从头扫到需要的数据行这个消耗,这也会产生上面提到的深度分页问题。

深度分页问题和各大厂的问题解决

 深度分页问题到底是什么?没错limit 10000,10这就是一个深度分页问题。

我们再访问网站的时候,应该遇到过数据分页展示的情况,我们如果想看第5页的就按前端 的第五页面,如果我们想要看第10000页,有的网站还会给用户搜索栏输入10000回车就可以看到第10000页的数据,但是这就产生了深度分页问题。会从第0行扫描到第10000页开头的行,这无疑是很消耗时间的,甚至如果不是使用上述提到的优化语句就算是limit 10000,10     执行计划是全表扫描,这无疑是很浪费时间的。这个问题怎么解决?无解,使用上面的优化语句已经是在语句方面的最高效的方式了。

那个大厂是怎么处理的呢?

用我的话总结:用户没有权力去规定一个页面的数据量,这就是后端定义好也就是写死的。

查看符合条件的全部数据也就是全表扫描,如果用户不能规定offset和size的大小,这两个变量都是由后端代码规定,那效率被影响的几率就不会很大。我们来后端的看看伪代码。

int start = 0;//这是定义每个页起始的行数据id
for{
    datas = select * from table where id > start order by id limit 100;
    if(datas.length() == 0) break;
    fanhuishuju(datas);
    start = get_max_start(datas);
}

这样就关于offset的设置就循环由代码进行决定,也就是start就是开始的行,注意start是主键值,这是由主键值推出起始行的经典代码。 

上述说过一个情况——搜索栏输入哪页就看哪页这样的方式有必要存在吗,这样只会拉低效率,所以百度的时候没有这个搜索框,而且只有五个页面供你选择,剩下的只能慢慢的去翻页。其实我们在百度的时候大多也就看前3页,往后的页面就不看了。

我们经常刷的抖音短视频的设计就是根基上面的代码,用户只能上滑下滑决定想看的视频,这样就能保证查询的效率,不会出现深度分页的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 NRF24L01 无线收发模块进行远程控制

NRF24L01 是一款基于 2.4GHz 射频通信的低功耗无线收发模块,具有高性能和稳定性,适用于远程控制和数据传输应用。本文将介绍如何使用 NRF24L01 模块进行远程控制,包括硬件的连接和配置,以及相应的代码示例。 一、引言 NRF24L01 是…

k8s报错

报错: 这个错误信息表明你的容器运行时(container runtime)没有正常运行,具体是因为CRI(容器运行时接口)v1版本的API没有为特定的端点实现。这通常发生在使用containerd作为容器运行时时。错误信息中提到的…

@RequestMapping处理请求异常

使用RequestMapping不指定请求方式,多种请求方式都支持。 Get格式FORM_URLENCODED Content-Typeapplication/x-www-form-urlencoded URL形式传参,请求体里面的内容是:usernamejohnexample.com&passwordsecretpassword&grant_type…

1.2 Ubauntu 使用

一、完成VMware Tools安装 双击 VMwareTool 打开 Ubuntu 终端快捷键 AltControlT 切换汉语的快捷键是Alt空格 ls 打印出当前所在目录中所有文件和文件夹 cd 桌面 进入桌面文件夹 sudo ./vmware-install.pl 安装tool,输入之前设置的密码。 地址默认,按…

论文阅读——Img2LLM(cvpr2023)

arxiv:[2212.10846] From Images to Textual Prompts: Zero-shot VQA with Frozen Large Language Models (arxiv.org) 一、介绍 使用大语言模解决VQA任务的方法大概两种:multi-modal pretraining and language-mediated VQA,即多模态预训练…

web:[NPUCTF2020]ReadlezPHP

题目 打开页面显示如下 没发现其他的线索,查看源代码 发现一个网址,访问这个页面查看 进行代码审计 这段代码是一个简单的 PHP 类,名为 HelloPhp。它有两个公共属性 $a 和 $b,并在构造函数中将它们分别初始化为字符串 "Y-m-…

Linux命令与shell脚本编程大全【读书笔记 + 思考总结】

Linux命令与shell脚本编程大全 第 1 章 初识Linux shellLinux的组成及关系结构图是什么?Linux系统内核的作用是什么?内核的主要功能是什么?(4点)物理内存和虚拟内存是什么关系?内核如何实现虚拟内存&#x…

zabbix 监控

zabbit 监控 非常成熟的监控软件。 运维人员,尽快系统服务器的状态,网站的流量,服务进程的运行状态。 保证整个集群的工作正常。7*24 zabbix是什么: web界面提供的一种可视化监控服务软件。 分布式的方式系统监控以及网络监控…

NodeJs(一):初识nodejs、模块化、CommonJS、ESModule等

目录 (一)Nodejs简介 1.nodejs是什么 2.nodejs架构 3.nodejs的应用场景 (二)准备工作 1.安装nodejs 2.nodejs版本管理工具 (三)nodejs的使用 1.node的输入 2.node的输出 3.其他的console方法 (四)全局对象 1.常见的全局对象 2.特殊的全局对象 3.global和window的…

用友U8 ERP和面粉行业专版系统接口集成方案

面粉加工行业面临着数据管理和业务流程自动化的挑战。众诚ERP系统和用友U8系统的数据集成是解决这一挑战的关键。 解决方案 轻易云平台提供了一套完善的数据同步和集成解决方案,包括以下几个方面: 基础资料同步:包括物料、客户、供应商、仓…

matlab 路面裂缝检测识别系统设计GUI

1、内容简介 略 23-可以交流、咨询、答疑 2、内容说明 路面裂缝检测识别系统设计GUI 基于matlab的GUI设计路面裂缝检测识别系统 matlab、GUI、直方图、裂缝检测、二值化 3、仿真分析 4、参考论文 略 链接:https://pan.baidu.com/s/1AAJ_SlHseYpa5HAwMJlk…

​LeetCode解法汇总2661. 找出叠涂元素

目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 给你一个下…

基于PHP的高中生物学习平台

有需要请加文章底部Q哦 可远程调试 基于PHP的高中生物学习平台 一 介绍 此高中生物学习平台基于原生PHP开发,数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈:phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 …

Unittest(1):unittest单元测试框架简介setup前置初始化和teardown后置操作

unittest单元测试框架简介 unittest是python内置的单元测试框架,具备编写用例、组 织用例、执行用例、功能,可以结合selenium进行UI自动化测 试,也可以结合appium、requests等模块做其它自动化测试 官方文档:https://docs.pytho…

CSS 多主题切换思路

前言 本篇仅提供多主题切换思路,示例简单且清晰。 实现 步骤一:多主题(颜色)定义 定义根伪类 :root,代码第 2 和 7 行。分别定义了默认和带参数的伪类;定义 CSS 变量,注意变量名需要以两个减号(--&…

如何选择适合长期投资的股票板块?

大家在学习炒股的过程中肯定没少听“板块”这个词,新手可能一脸懵逼,板块到底是啥意思?为什么会有这么多板块? 一、什么是股票板块?常见的板块分类有哪些? 板块理解起来其实很简单,它就是一种分…

API成批分配漏洞介绍与解决方案

一、API成批分配漏洞介绍 批量分配:在API的业务对象或数据结构中,通常存在多个属性,攻击者通过篡改属性值的方式,达到攻击目的。比如通过设置user.is_admin和user.is_manager的值提升用户权限等级;假设某API的默认接口…

从自动化、数字化到智能化,鸿蒙与制造业的双向奔赴

终端万物互联,商业竞争瞬息万变,制造企业面临着数字化转型与产品智能化升级的双重考验。鸿蒙操作系统以统一操作系统方案,可以为制造企业解决设备生态碎片化以及跨终端对接问题,提供安全性、流畅度、多屏协同等功能,实…

将本地项目推送到github

欢迎大家到我的博客浏览。将本地项目推送到github | YinKais Blog 本地项目上传至 GitHub<!--more--> 1、进入项目根目录&#xff0c;初始化本地仓库 git init 2、创建密钥&#xff1a;创建 .ssh 文件夹&#xff0c;并进入 .ssh 文件夹 mkdir .ssh cd .ssh/ 3、生成…

Robotframework自动化常见问题总结

Robotframework自动化新手常见问题总结 1. 经常有人问这个元素找不到&#xff0c;一般先排除这两个地方&#xff0c;再自己找找 A&#xff1a;是否等待了足够的时间让元素加载 (增加sleep xx, wait Until xxx) B: 仔细查查&#xff0c;这个元素是否进入到另一个frame了 (sel…