0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

为什么分页场景下mysql请求速度非常慢

Android编程精选 来源:掘金 作者:牛牛码特 2021-10-08 14:46 次阅读

来源丨https://juejin.cn/post/6844903939247177741

从一个问题说起五年前在tx的时候,发现分页场景下,mysql请求速度非常慢。数据量只有10w的情况下,select xx from 单机大概2,3秒。我就问我导师为什么,他反问“索引场景,mysql中获得第n大的数,时间复杂度是多少?”

答案的追寻确认场景假设status上面有索引。select * from table where status = xx limit 10 offset 10000。会非常慢。数据量不大的情况就有几秒延迟。

小白作答瞎猜了个log(N),心想找一个节点不就是log(N)。自然而然,导师让我自己去研究。

这一阶段,用了10分钟。

继续解答仔细分析一下,会发现通过索引去找很别扭。因为你不知道前100个数在左子树和右子数的分布情况,所以其是无法利用二叉树的查找特性。通过学习,了解到mysql的索引是b+树。

0c76bb4e-23df-11ec-82a8-dac502259ad0.png

看了这个图,就豁然开朗了。可以直接通过叶子节点组成的链表,以o(n)的复杂度找到第100大的树。但是即使是o(n),也不至于慢得令人发指,是否还有原因。

这一阶段,主要是通过网上查资料,断断续续用了10天。

系统学习这里推荐两本书,一本《MySQL技术内幕 InnoDB存储引擎》,通过他可以对InnoDB的实现机制,如mvcc,索引实现,文件存储会有更深理解。

第二本是《高性能MySQL》,这本书从着手使用层面,但讲得比较深入,而且提到了很多设计的思路。

两本书相结合,反复领会,mysql就勉强能登堂入室了。

这里有两个关键概念:

聚簇索引:包含主键索引和对应的实际数据,索引的叶子节点就是数据节点

辅助索引:可以理解为二级节点,其叶子节点还是索引节点,包含了主键id。

即使前10000个会扔掉,mysql也会通过二级索引上的主键id,去聚簇索引上查一遍数据,这可是10000次随机io,自然慢成哈士奇。这里可能会提出疑问,为什么会有这种行为,这是和mysql的分层有关系,limit offset 只能作用于引擎层返回的结果集。换句话说,引擎层也很无辜,他并不知道这10000个是要扔掉的。以下是mysql分层示意图,可以看到,引擎层和server层,实际是分开的。

直到此时,大概明白了慢的原因。这一阶段,用了一年。

触类旁通此时工作已经3年了,也开始看一些源码。在看完etcd之后,看了些tidb的源码。无论哪种数据库,其实一条语句的查询,是由逻辑算子组成。

逻辑算子介绍 在写具体的优化规则之前,先简单介绍查询计划里面的一些逻辑算子。

DataSource 这个就是数据源,也就是表,select * from t 里面的 t。

Selection 选择,例如 select xxx from t where xx = 5 里面的 where 过滤条件。

Projection 投影, select c from t 里面的取 c 列是投影操作。

Join 连接, select xx from t1, t2 where t1.c = t2.c 就是把 t1 t2 两个表做 Join。

选择,投影,连接(简称 SPJ) 是最基本的算子。其中 Join 有内连接,左外右外连接等多种连接方式。

select b from t1, t2 where t1.c = t2.c and t1.a 》 5 变成逻辑查询计划之后,t1 t2 对应的 DataSource,负责将数据捞上来。上面接个 Join 算子,将两个表的结果按 t1.c = t2.c连接,再按t1.a 》 5做一个 Selection 过滤,最后将 b 列投影。下图是未经优化的表示:

所以说不是mysql不想把limit, offset传递给引擎层,而是因为划分了逻辑算子,所以导致无法直到具体算子包含了多少符合条件的数据。

怎么解决《高性能MySQL》提到了两种方案

方案一

根据业务实际需求,看能否替换为下一页,上一页的功能,特别在iosandroid端,以前那种完全的分页是不常见的。这里是说,把limit, offset,替换为》辅助索引(即搜索条件)id的方式。该id再调用时,需要返回给前端。

方案二

正面刚。这里介绍一个概念:索引覆盖:当辅助索引查询的数据,只有id和辅助索引本身,那么就不必再去查聚簇索引。

思路如下:select xxx,xxx from in (select id from table where second_index = xxx limit 10 offset 10000) 这句话是说,先从条件查询中,查找数据对应的数据库唯一id值,因为主键在辅助索引上就有,所以不用回归到聚簇索引的磁盘去拉取。再通过这些已经被limit出来的10个主键id,去查询聚簇索引。这样只会十次随机io。在业务确实需要用分页的情况下,使用该方案可以大幅度提高性能。通常能满足性能要求。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6852

    浏览量

    88769
  • SQL
    SQL
    +关注

    关注

    1

    文章

    753

    浏览量

    44048

原文标题:分页场景(limit,offset)为什么会慢?

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    MySQL编码机制原理

    前言 一位读者在本地部署 MySQL 测试环境时碰到一个问题,我觉得挺有代表性的,所以写篇文章介绍一,看完相信你会对 MySQL 的编码机制有最本质的了解,本文的目录结构如下 读者问题简介
    的头像 发表于 11-09 11:01 117次阅读

    对I/O寄存器的访问速度慢是怎么回事?

    对 I/O 寄存器的访问速度慢
    发表于 07-12 09:29

    ESP32外挂FLASH下载速度慢怎么解决?

    ESP32 外挂FLASH 下载速度慢,小于500K的固件能下载,但下载速度只有100kbits/s1.5M 固件下载失败 Flash型号为P25Q32H,有办法让此Flash 工作在QIO模式吗。
    发表于 06-21 15:01

    iOS和Android蓝牙传输速度非常,有没有提高的方法?

    iOS和Android蓝牙传输速度非常,有没有提高的方法?
    发表于 06-05 06:53

    MySQL的整体逻辑架构

    支持多种存储引擎是众所周知的MySQL特性,也是MySQL架构的关键优势之一。如果能够理解MySQL Server与存储引擎之间是怎样通过API交互的,将大大有利于理解MySQL的核心
    的头像 发表于 04-30 11:14 418次阅读
    <b class='flag-5'>MySQL</b>的整体逻辑架构

    STM32F429做的PIL仿真速度非常的原因?

    ,但是速度非常。不知道是否STM32F429的参数设定有问题。有没有哪位大神做过相关的仿真。补充:仿真中控制器开关频率是5000khz,采样时间为5e^-5s。 先谢谢了!
    发表于 04-11 07:28

    STM32H743 IO速度慢是什么原因造成的?

    STM32H743 IO速度慢,实际能到多少.IO翻转速度只有16M,读一个IO要很多个时钟周期,是都这样的吗。
    发表于 03-21 07:16

    查询SQL在mysql内部是如何执行?

    我们知道在mySQL客户端,输入一条查询SQL,然后看到返回查询的结果。这条查询语句在 MySQL 内部到底是如何执行的呢?本文跟大家探讨一哈,我们先来看下MySQL基本架构~
    的头像 发表于 01-22 14:53 526次阅读
    查询SQL在<b class='flag-5'>mysql</b>内部是如何执行?

    M481系列KEIL选择ARM5编译器 ,编译速度非常怎么解决?

    M481系列,如果KEIL选择ARM5编译器 ,编译速度非常
    发表于 01-16 06:51

    mysql密码忘了怎么重置

    mysql密码忘了怎么重置  MySQL是一种开源的关系型数据库管理系统,密码用于保护数据库的安全性和保密性。如果你忘记了MySQL的密码,可以通过以下几种方法进行重置。 方法一:使用MySQ
    的头像 发表于 12-27 16:51 6141次阅读

    mybatis逻辑分页和物理分页的区别

    这两种分页方式的区别。 逻辑分页是在数据库中执行查询时使用的一种分页方式。这种方式是通过在查询语句中添加LIMIT或OFFSET关键字来限制结果集的大小和偏移量来实现的。常见的逻辑分页
    的头像 发表于 12-03 14:54 837次阅读

    SQLite、MySQL和PostgreSQL的差异与应用场景

    我们就来讲讲三个常用的免费开源的关系型数据库SQLite、MySQL和PostgreSQL,大概地了解一这三个数据库的差异与应用场景。 Part1 概述 数据库可以分商业数据库和免费数据库,常见的商业
    的头像 发表于 11-24 15:44 2118次阅读

    MySQL性能优化方法

    MySQL 性能优化是一项关键的任务,可以提高数据库的运行速度和效率。以下是一些优化方法,包括具体代码和详细优化方案。
    的头像 发表于 11-22 09:59 541次阅读

    MySQL数据库基础知识

    的基础知识,包括其架构、数据类型、表操作、查询语句和数据导入导出等方面。 MySQL 数据库架构 MySQL 数据库由多个组件组成,包括服务器、存储引擎和客户端等。MySQL 服务器是数据库的核心,它负责处理客户端的
    的头像 发表于 11-21 11:09 939次阅读

    MySQL导出的步骤

    MySQL是一种常用的关系型数据库管理系统,用于存储和管理大量的结构化数据。在实际应用中,我们经常需要将MySQL数据库中的数据导出到其他地方,如备份数据、数据迁移、数据分析等。下面是使用MySQL
    的头像 发表于 11-21 10:58 748次阅读