java八股文面试[数据库]——分页查询优化

news2025/1/12 18:08:29
  • 一般性分页

    一般的分页查询使用简单的 limit 子句就可以实现。limit格式如下:

    SELECT * FROM 表名 LIMIT [offset,] rows
    • 第一个参数指定第一个返回记录行的偏移量,注意从0开始;

    • 第二个参数指定返回记录行的最大数目;

    • 如果只给定一个参数,它表示返回最大的记录行数目;

    思考1:如果偏移量固定,返回记录量对执行时间有什么影响?

    select * from user limit 10000,1;
    select * from user limit 10000,10;
    select * from user limit 10000,100;
    select * from user limit 10000,1000;
    select * from user limit 10000,10000;

    结果:在查询记录时,返回记录量低于100条,查询时间基本没有变化,差距不大。随着查询记录量越大,所花费的时间也会越来越多

    思考2:如果查询偏移量变化,返回记录数固定对执行时间有什么影响?

    select * from user limit 1,100;
    select * from user limit 10,100;
    select * from user limit 100,100;
    select * from user limit 1000,100;
    select * from user limit 10000,100;

    结果:在查询记录时,如果查询记录量相同,偏移量超过100后就开始随着偏移量增大,查询时间急剧的增加。(这种分页查询机制,每次都会从数据库第一条记录开始扫描,越往后查询越慢,而且查询的数据越多,也会拖慢总查询速度。)

  • 分页优化方案

    优化1: 通过索引进行分页

    直接进行limit操作 会产生全表扫描,速度很慢. Limit限制的是从结果集的M位置处取出N条输出,其余抛弃.

    假设ID是连续递增的,我们根据查询的页数和查询的记录数可以算出查询的id的范围,然后配合 limit使用

    EXPLAIN SELECT * FROM user WHERE id  >= 100001 LIMIT 100;

    优化2:利用子查询优化

    -- 首先定位偏移位置的id
    SELECT id FROM user_contacts LIMIT 100000,1;
    ​
    -- 根据获取到的id值向后查询.
    EXPLAIN SELECT * FROM user_contacts WHERE id >=
    (SELECT id FROM user_contacts LIMIT 100000,1) LIMIT 100;

    原因:使用了id做主键比较(id>=),并且子查询使用了覆盖索引进行优化。

常用分页查询

(1)未用索引

对于小数据量的表,我们经常采用(select * from table limit x,y)的形式来完成分页查询。例如:

select * from areas limit 0,20; (第一页)
select * from areas limit 20,20;(第二页)
select * from areas limit 40,20;(第三页)

使用这种方式进行查询并没有用到索引,所以会进行全表查询。当数据量较大时,速度会非常慢。

在这里插入图片描述

(2)使用索引

当用到索引时,扫描记录数会明显降低。下面使用explain来查看查询情况:

explain select * from areas order by id desc limit 300,20;

在这里插入图片描述
这里使用order by id 目的就是要使用id中的主键索引,否则我们的查询就会变为全表检索了。这里查询出的rows代表了我们查询时的扫描记录数,如果limit起始点是300那么记录数为320,如果起始点是1000000,那么查询记录数为1000020,这也就意味着,起始点越往后,查询速度越慢,如果起始点到了末尾,那么就相当于全表检索了,此时索引也就失去了意义。

这种索引的查询方式是我们经常使用的,但是这种查询需要进行回表,即需要进行二次查询,为了尽可能的避免回表操作,我们推荐使用延迟关联来进行查询,来最大程度的使用覆盖索引。

分页查询优化

1 最大id查询法

select * from areas where id>2000 limit 20;

在这里插入图片描述
本次测试数据一共有3750条数据,id>2000,即查询的记录数为id=2000之后的数据。

注意:
最大id查询法只能适用于自增主键,uuid生成的主键不适合这种方式。

2 between and

select * from user where id between 2000 and 2010;

在这里插入图片描述
这种方式也 只能适用于自增主键,并且id没有断裂,否则不推荐这种方式,使用BETWEEN AND的时候查询出来11条记录,这里需要注意BETWEEN AND包含了两边的边界条件。

3 limit id

select * from areas where id>(select id from areas limit 2000,1)
limit 20;

在这里插入图片描述
这样虽然也是扫描了3750行记录,但是由于id是主键,拥有主键索引,所以对一个主键id进行limit范围查询,相比于select * from areas limit 2000,20;速度会快很多。

SUBQUERY:在SELECT或WHERE列表中包含了子查询

4 延迟关联

覆盖索引:InnoDB的二级索引在叶子节点中保存了行的主键值,所以二级主键能够覆盖查询,可以避免对主键索引的二次查询。所需的数据列只需要从索引中就能获得,不用再去回表,即不必再去主键索引区查找数据行。

延迟关联 :为了尽可能的提高sql语句的查询能力,让sql语句中的部分使用覆盖索引来查询

我们在aid字段上创建了一个普通索引keyin.

select * from areas a join (select aid from areas 
limit 2000,20) b on a.aid = b.aid;

在这里插入图片描述
在查询的第一个阶段我们使用了覆盖索引select aid from areas limit 2000,20,在这个from子句的子查询中找到匹配的aid.然后根据这些aid在外层查询匹配获取所有的列值。虽然不能使用索引覆盖整个查询,但总算比完全无法利用索引覆盖的好。

注意:

  • 4中的limit id也用到了覆盖索引,但是我们推荐使用延迟关联join来查询,避免使用子查询。当字段比较多,类型的长度比较长的时候,延迟关联也是比较有优势的。
  • select操作中使用了覆盖索引时,explain中的extra中会显示Using index.
  • id值越大,查询优先级越高。
  • 在FROM列表中包含的子查询被标记为DERIVED(衍生),devived2指的是areas的衍生表

5 分表查询

mysql推荐一张表的存储不要超过500w数据,查询400w不到1秒对于一般的查询来说已经可以了,如果还要更快的话,建议使用分表存储,分表又分两种情况,水平分表于垂直分表。

(1)水平分表
假如一张表的原始数据有900w条数据,可以分三张表存储,每张表存300万的数据,这样查询的时候压力就会小很多,并且效率也很高很多,那问题来了,如何这个水平水表如何实现呢?像可以借助mycat之类的中间件,阿里云也提供了数据库的分表技术,当然,你也可以自己手写分表,但是自己手写分表的时候需要注意id重复以及如何定义搭配当前id在那张表中,算法推荐使用hash值。

(2)垂直分表
假如记录有100w,按正常来说查询速度应该不会太慢,但是由于这张表的字段超多,而且还有很多text类型的字段,这个时候我们可以将占用空间比较小的字段分在一张表,占用空间比较大的字段分在另一张表,两张表一一关联,这样,查询的时候就会快很多了。

(3)冷热表
冷热表也是一种分表思想,例如银行查询账单的时候会发现只能查询近几个月的数据,之前的数据需要去柜台查询历史账单,银行查询数据就是用的冷热表的设计思想。

新建两个相同的表,一张表存放近三个月的记录:a表,另一张表存放三个月之前的数据:b表,用户产生的新记录可以存放在a表中,可以在每天凌晨的时候定时扫描a表,只要记录已经在三个月之前了,我们就可以将记录迁移到b表中,对于用户来说,查询近三个月的数据时他们比较敏感的,三个月之前的数据他们查询的可能并不多,所以这样的设计完全是合理的。

6 索引

添加索引可以提高查询效率,如果分页查询牵扯到条件的话,我们可以给条件添加索引,数据库会维护一张对应的索引表,查询的时候会先查询索引表,根据索引表返回的记录直接查询记录表,这样也减少了扫描的行数,但是需要注意,只要发生一下几点,索引都有可能不会被触发,一定要注意。

  • 查询条件使用is not null
  • like语句,比如 keyword like ‘%笔记本’,索引失效,%不能再最前面。
  • OR 前后条件中只要有一个没有添加索引,那么将扫描全表,索引失效。
  • 组合索引:使用组合索引的时候必要要带上第一个索引的字段,否则组合索引不生效。
  • > 、< 、 <>。
  • 没有单引号的字符串

7 缓存

把查询结果缓存到redis中,这样直接读取内存,而不用查询硬盘数据。

注意:
查询优化的重点就在于如何能扫描最少的记录,返回查询的结果,使用缓存来降低数据库的访问,但这治标不治本,只有写出漂亮的sql才能让程序立于不败之地。

知识来源:马士兵教育

分页查询优化方案总结_长不大的大灰狼的博客-CSDN博客

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

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

相关文章

Nomad 系列-快速上手

系列文章 Nomad 系列文章 Nomad 重要术语 Nomad 安装设置相关术语 agent - 代理。Agent 是在 Server&#xff08;服务器&#xff09; 或 Client&#xff08;客户端&#xff09; 模式下运行的 Nomad 进程。client - 客户端。Nomad 客户端负责运行分配给它的任务。它还向服务器…

JVM----GC(垃圾回收)详解

一、Automatic Garbage Collection&#xff08;垃圾回收&#xff09;简介 Automatic Garbage Collection &#xff08;自动垃圾回收&#xff09;是JVM的一个特性&#xff0c;JVM会启动相关的线程&#xff0c;该线程会轮训检查heap memeory&#xff0c;并确定哪些是未被引用的(…

滚动菜单 flutter

想实现这个功能&#xff1a; 下面的代码可以实现&#xff1a; import package:flutter/material.dart;void main() > runApp(MyApp());class MyApp extends StatelessWidget {static const String _title Flutter Code Sample;overrideWidget build(BuildContext context)…

【MySQL】CRUD (增删改查) 基础

CRUD&#xff08;增删改查&#xff09;基础 一. CRUD二. 新增 &#xff08;Create&#xff09;1. 单行数据 全列插入2. 多行数据 指定列插入 三. 查询&#xff08;Retrieve&#xff09;1. 全列查询2. 指定列查询3. 查询字段为表达式4. 别名5. 去重&#xff1a;DISTINCT6. 排序…

【算法】希尔 (Shell) 排序 详解

希尔排序 详解 希尔排序代码实现 排序&#xff1a; 排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a; 假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#x…

生信豆芽菜-机器学习筛选特征基因

网址&#xff1a;http://www.sxdyc.com/mlscreenfeature 一、使用方法 1、准备数据 第一个文件&#xff1a;特征表达数据 第二个文件&#xff1a;分组信息&#xff0c;第一列为样本名&#xff0c;第二列为患者分组 第三个文件&#xff1a;分析基因名 2、选择机器学习的方…

[学习笔记]CS224W

资料&#xff1a; 课程网址 斯坦福CS224W图机器学习、图神经网络、知识图谱【同济子豪兄】 斯坦福大学CS224W图机器学习公开课-同济子豪兄中文精讲 图的基本表示 图是描述各种关联现象的通用语言。与传统数据分析中的样本服从独立同分布假设不一样&#xff0c;图数据自带关联…

学习SpringMvc第二战之【SpringMVC之综合案例】

目录 一. 参数传递 1.前期准备工作&#xff08;替换pom.xml中的部分依赖&#xff09; 1.1将log4j替换成为slf4j(将打印语句替换成为日志文件输出结果) 2.正式操作 1.基础传参 1.1创建方法&#xff0c;用于验证传参 1.2构建界面回显 1.3设置访问路径&#xff08;localho…

【PHP代码审计】反序列化漏洞实战

文章目录 概述资源下载地址Typecho代码审计-漏洞原理call_user_func()_applyFilter()、get()与__get__toString()__construct()install.php POC利用漏洞利用复现利用链执行phpinfo()GET利用POST利用 getshell生成payload漏洞利用蚁剑连接 总结 概述 序列化&#xff0c;“将对象…

污水处理厂3D数字孪生三维可视系统降低设备风险隐患

当相对传统与保守的水务行业&#xff0c;与激进与开放的互联网发生碰撞之后&#xff0c;产生了最好的一个名词是&#xff1a;“智慧水务”&#xff0c;谈及智慧水务&#xff0c;自然免不了当下最具热度的技术“元宇宙”&#xff0c;水资源再生是我国追求高质量发展的新策略&…

fastadmin列表,关联筛选查询

fastadmin文章表关联分类表&#xff0c;分类筛选默认按分类名模糊查询&#xff0c;项目需求是下拉选择分类&#xff0c;根据分类id直接筛选。最终效果如下图。 var table $("#table");//在普通搜索渲染后table.on(post-common-search.bs.table, function (event, ta…

Elasticsearch脑裂

文章目录 Elasticsearch脑裂 Elasticsearch脑裂 Elasticsearch脑裂是指由于网络分区或节点间通信故障导致集群中的节点无法互相正常通信&#xff0c;从而导致数据不一致的情况。这可能会导致集群中的多个节点同时自认为是主节点&#xff08;master&#xff09;&#xff0c;并开…

mysql(十)mysql主从复制--主库切换

概述 可能为了更迭升级服务器&#xff0c;或者主库出现问题&#xff0c;又或者只是希望重新分配容量&#xff0c;此时需要切换主库。 如果这是计划内的切换&#xff0c;会相对容易点。只需要在从库上使用CHANGE MASTER TO命令&#xff0c;并设置合适的值。大多数的值都是可选…

大数据技术之Hadoop:使用命令操作HDFS(四)

目录 一、创建文件夹 二、查看指定目录下的内容 三、上传文件到HDFS指定目录下 四、查看HDFS文件内容 五、下载HDFS文件 六、拷贝HDFS文件 七、HDFS数据移动操作 八、HDFS数据删除操作 九、HDFS的其他命令 十、hdfs web查看目录 十一、HDFS客户端工具 11.1 下载插件…

OpenWrt系统内核设置

系统内核设置&#xff1a;OpenWrt也是一个 Linux 操作系统&#xff0c;因此它和其他Linux 操作系统一样&#xff0c; 可以通过一些配置文件配置。 一、/etc/sysctl.conf 配置文件 这个文件是系统启动预加载的内核配置文件&#xff0c;通过sysctl命令读取和设置到系统当中。这个…

openGauss学习笔记-62 openGauss 数据库管理-两地三中心跨Region容灾

文章目录 openGauss学习笔记-62 openGauss 数据库管理-两地三中心跨Region容灾62.1 基于流式复制的异地容灾解决方案62.1.1 概述62.1.2 规格与约束62.1.2.1 特性规格62.1.2.2 特性约束 62.1.3 影响容灾性能指标的GUC参数设置62.1.3.1 检查点相关参数设置的影响62.1.3.2 极致RTO…

android 车载widget小部件部分详细源码实战开发-千里马车载车机framework开发实战课程

官网参考链接&#xff1a;https://developer.android.google.cn/develop/ui/views/appwidgets/overview 1、什么是小部件 App widgets are miniature application views that can be embedded in other applications (such as the home screen) and receive periodic updates…

LED显示屏安全亮度参数设置方法和防护

随着LED显示屏应用领域越来越广&#xff0c;但其高亮度造成的光污染&#xff0c;常受到的人们的诟病。为了更好的避免光污染&#xff0c;我整理了一些关于LED显示安全亮度参数设置方法和安全防护措施。你知道LED广告牌是如何工作的吗&#xff1f; 设置LED显示屏的安全亮度参数和…

android上架备案公钥和md5获取工具

最近很多公司上架遇到了一个问题&#xff0c;就是要提供app的备案证明&#xff0c;现在android上架都需要备案了&#xff0c;但是我们的证书都是通过工具生成的&#xff0c;哪里知道公钥和md5那些东西呢&#xff1f;无论安卓备案还是ios备案都需要提供公钥和md5。 包括ios的备案…

ChatGPT Prompting开发实战(五)

一、如何编写有效的prompt 对于大语言模型来说&#xff0c;编写出有效的prompt能够帮助模型更好地理解用户的意图(intents)&#xff0c;生成针对用户提问来说是有效的答案&#xff0c;避免用户与模型之间来来回回对话多次但是用户不能从LLM那里得到有意义的反馈。本文通过具体…