MySQL数据查询优化

news2024/11/27 22:46:19

MySQL调优是开发中必不可少的内容,以下是对MySQL查询性能优化的部分总结

1. explain关键字的使用

        explain关键字可以模拟优化器执行sql查询语句,获取sql的执行信息,使用方法:

explain+sql语句

        1.1 字段详解

        

  1.  id(select 查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序)

    ①id相同,执行顺序从上往下
    ②id全不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
    ③id部分相同,执行顺序是先按照数字大的先执行,然后数字相同的按照从上往下的顺序执行

  2. select_type(查询类型,用于区别普通查询、联合查询、子查询等复杂查询)
    SIMPLE :简单的select查询,查询中不包含子查询或UNION
    PRIMARY:查询中若包含任何复杂的子部分,最外层查询被标记为PRIMARY
    SUBQUERY:在select或where列表中包含了子查询
    DERIVED:在from列表中包含的子查询被标记为DERIVED,MySQL会递归执行这些子查询,把结果放在临时表里
    UNION:若第二个select出现在UNION之后,则被标记为UNION,若UNION包含在from子句的子查询中,外层select将被标记为DERIVED
    UNION RESULT:从UNION表获取结果的select

  3. table(显示这一行的数据是关于哪张表的)

  4. type(显示查询使用了那种类型,从最好到最差依次排列 system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
    system:表只有一行记录(等于系统表),是 const 类型的特例,平时不会出现
    ②const:表示通过索引一次就找到了,const 用于比较 primary key 或 unique 索引,因为只要匹配一行数据,所以很快,如将主键置于 where 列表中,mysql 就能将该查询转换为一个常量
    eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
    ref:非唯一性索引扫描,范围匹配某个单独值得所有行。本质上也是一种索引访问,他返回所有匹配某个单独值的行,然而,它可能也会找到多个符合条件的行,多以他应该属于查找和扫描的混合体
    range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般就是在你的where语句中出现了between、<、>、in等的查询,这种范围扫描索引比全表扫描要好,因为它只需开始于索引的某一点,而结束于另一点,不用扫描全部索引
    index:Full Index Scan,index于ALL区别为index类型只遍历索引树。通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)
    ALL:Full Table Scan,将遍历全表找到匹配的行
     一般来说,得保证查询至少达到range级别,最好到达ref

  5. possible_keys(显示可能应用在这张表中的索引,一个或多个,查询涉及到的字段若存在索引,则该索引将被列出,但不一定被查询实际使用)

  6. key
    实际使用的索引,如果为NULL,则没有使用索引

    查询中若使用了覆盖索引,则该索引和查询的 select 字段重叠,仅出现在key列表中

  7. key_len
    用于处理查询的索引长度,表示索引中使用的字节数。通过这个值,可以得出一个多列索引里实际使用了哪一部分。

    注:key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。另外,key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。

  8. ref

    显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值 ,如果可能,是一个常量const。

  9. rows

    表示MySQL根据表统计信息及索引选用情况,大致估算的找到所需的目标记录所需要读取的行数,不是精确值。这个值非常直观的显示 sql 效率好坏, 原则上 rows 越少越好

  10. filtered

    当你的索引统计直接获取了需要的所有数据时,就会显示100
    因此一个比较低filtered值表示需要有一个更好的索引,假如type=all,表示以全表扫描的方式得到1000条记录,且filtered=0.1%,表示只有1条记录是符合搜索条件的。

  11. extra

    Using filesort
    MySQL有两种方式可以生成有序的结果,通过排序操作或者使用索引,当Extra中出现了Using filesort 说明MySQL使用了后者,但注意虽然叫filesort但并不是说明就是用了文件来进行排序,只要可能排序都是在内存里完成的。大部分情况下利用索引排序更快,所以一般这时也要考虑优化查询了。使用文件完成排序操作,这是可能是ordery by,group by语句的结果,这可能是一个CPU密集型的过程,可以通过选择合适的索引来改进性能,用索引来为查询结果排序。

    Using temporary
    用临时表保存中间结果,常用于GROUP BY 和 ORDER BY操作中,一般看到它说明查询需要优化了,就算避免不了临时表的使用也要尽量避免硬盘临时表的使用。

    Not exists
    MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行, 就不再搜索了。

    Using index
    说明查询是覆盖了索引的,不需要读取数据文件,从索引树(索引文件)中即可获得信息。如果同时出现using where,表明索引被用来执行索引键值的查找,没有using where,表明索引用来读取数据而非执行查找动作。这是MySQL服务层完成的,但无需再回表查询记录。

    Using index condition
    这是MySQL 5.6出来的新特性,叫做“索引条件推送”。简单说一点就是MySQL原来在索引上是不能执行如like这样的操作的,但是现在可以了,这样减少了不必要的IO操作,但是只能用在二级索引上。

    Using where
    使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。注意:Extra列出现Using where表示MySQL服务器将存储引擎返回服务层以后再应用WHERE条件过滤。

    Using join buffer
    使用了连接缓存:Block Nested Loop,连接算法是块嵌套循环连接;Batched Key Access,连接算法是批量索引连接

    impossible where
    where子句的值总是false,不能用来获取任何元组

    select tables optimized away
    在没有GROUP BY子句的情况下,基于索引优化MIN/MAX操作,或者对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。

    distinct
    优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作

    参考链接

2. MySQL索引原理

  • 顾名思义,B-tree索引使用B-tree的数据结构存储数据,不同的存储引擎以不同的方式使用B-Tree索引,比如MyISAM使用前缀压缩技术使得索引空间更小,而InnoDB则按照原数据格式存储,且MyISAM索引在索引中记录了对应数据的物理位置,而InnoDB则在索引中记录了对应的主键数值。B-Tree通常意味着所有的值都是按顺序存储,并且每个叶子页到根的距离相同。

  • B-Tree索引驱使存储引擎不再通过全表扫描获取数据,而是从索引的根节点开始查找,在根节点和中间节点都存放了指向下层节点的指针,通过比较节点页的值和要查找值可以找到合适的指针进入下层子节点,直到最下层的叶子节点,最终的结果就是要么找到对应的值,要么找不到对应的值。整个B-tree树的深度和表的大小直接相关。

  • 全键值匹配:和索引中的所有列都进行匹配,比如查找姓名为zhang san,出生于1982-1-1的人

  • 匹配最左前缀:和索引中的最左边的列进行匹配,比如查找所有姓为zhang的人

  • 匹配列前缀:匹配索引最左边列的开头部分,比如查找所有以z开头的姓名的人

  • 匹配范围值:匹配索引列的范围区域值,比如查找姓在li和wang之间的人

  • 精确匹配左边列并范围匹配右边的列:比如查找所有姓为Zhang,且名字以K开头的人

  • 只访问索引的查询:查询结果完全可以通过索引获得,也叫做覆盖索引,比如查找所有姓为zhang的人的姓名

参考链接

3. 实例
以下是我的测试表device_everyday_count_value的表结构:

CREATE TABLE `device_everyday_count_value` (
  `sid` int NOT NULL AUTO_INCREMENT COMMENT '主键 序号 自增',
  `device_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '设备id',
  `device_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '设备名称',
  `node_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '点位id',
  `node_describe` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '点位描述',
  `count_value` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '统计值',
  `latest_value` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '当天最新的(最晚的)记录',
  `value_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '信号值属性(dict_device_valuetype)',
  `count_date` date DEFAULT NULL COMMENT '统计时间',
  PRIMARY KEY (`sid`) USING BTREE,
  KEY `idx_deviceId_countDate_countValue` (`device_id`,`count_date`,`count_value`) USING BTREE COMMENT 'deviceId,countDate,CountValue普通索引'
) ENGINE=InnoDB AUTO_INCREMENT=515 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='设备点位每日用能统计表';

1.1 select * 

explain select t1.* from `device_everyday_count_value` t1;

 

根据上图能够发现当我们使用select *时,索引是失效的而且扫描了全表

现在改为如下所示:

explain select  t1.device_id, t1.count_date from `device_everyday_count_value` t1;

发现索引生效了,所以应当避免使用select * 

1.2 where条件相等判断

explain select t1.device_id , t1.count_date from `device_everyday_count_value` t1 where t1.device_name = 'test';

发现没有走索引,且全表扫描。现改为如下所示:

explain select t1.device_id , t1.count_date from `device_everyday_count_value` t1 where t1.device_id = '20';

 

能够走索引,where过滤条件要符合最左原则。

1.3 回表

explain select  t1.device_name, t1.device_id, t1.count_date from `device_everyday_count_value` t1;

可以发现select字段中出现了没在索引列上的device_name,在执行的时候发现没有走索引并且type为all。现改为如下所示:

explain select  t1.device_id, t1.count_date from `device_everyday_count_value` t1;

能够发现索引生效了,并且没有回表,表名我们在使用的过程中最好覆盖索引,如果是比较常用的name属性可以考虑走缓存,然后数据库查询的时候只查询device_id

1.4 type---查询范围优化

1.4.1 引号问题

explain select  t1.device_id, t1.count_date from `device_everyday_count_value` t1 where t1.device_id > 1;

发现我们的type类型为index(system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL)是比较低的,

现改为如下所示:

explain select  t1.device_id, t1.count_date from `device_everyday_count_value` t1 where t1.device_id > '1';

我们type类型变为了range类型,查询范围优化了,通过表结构能够发现我们的device_id是varchar类型的虽然数据库存储的是数字,但是类型是字符串类型的所以我们应该加上引号

1.4.2 索引顺序

在执行前先device_id的索引顺序移动到第二位

执行以下代码:

explain select  t1.device_id, t1.count_date from `device_everyday_count_value` t1 where t1.device_id > '1';

接下来再将device_id的顺序移动到最后

执行同样的sql代码

explain select  t1.device_id, t1.count_date from `device_everyday_count_value` t1 where t1.device_id > '1';

可以发现我们的type的等级由range降为index了,索引我们在使用的时候需要符合最左前缀原则。

内容会持续更新,还会更新多表联合查询的优化处理以及注意事项!

锲而舍之,朽木不折;锲而不舍,金石可镂。——诗句出自:《荀子·劝学》

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

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

相关文章

Linux---在Xshell上配置软件包管理器yum

一、什么是yum 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软…

练习题(2024/5/12)

1二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target 9 输出: 4…

解决vue3项目打包后部署后某些静态资源图片不加载问题

目录 问题 原因 解决方案 问题 开发完项目打包并部署 然后访问时发现导航栏背景图片没加载 打开浏览器控制台发现这张图片报错404 原因 可能是因为在部署后的服务器环境中对中文文件名的支持不完善。服务器在解析 URL 时可能无法正确识别或编码中文字符&#xff0c;导致无…

数据结构(四)——二叉树和堆(下)

制作不易&#xff0c;三连支持一下呗&#xff01;&#xff01;&#xff01; 文章目录 前言一、二叉树链式结构的实现总结 前言 这篇博客我们将来了解普通二叉树的实现和应用&#xff0c;对大家之前分治和递归的理解有所挑战。 一、二叉树链式结构的实现 1.前置说明 在学习二叉…

网络编程套接字详解

目录 1. 预备介绍 2.网络字节序 3.udp网络程序 4.地址转换函数 5.udp网络编程 1.预备介绍 1.1源IP地址和目标IP地址 举个例子: 从北京出发到上海旅游, 那么源IP地址就是北京, 目标IP地址就是上海. 1.2 端口号 作用: 标识一个进程, 告诉OS这个数据交给那个进程来处理; (1)…

爱分析基于杭州云器Lakehouse实现成本最优的一体化管理,新一代数据平台的建设方式

导读 1.当前&#xff0c;企业在大数据和数据中台建设上取得成果&#xff0c;但数据开发管理仍具挑战性&#xff08;成本、效率、复杂度&#xff09;。 2.随数据平台领域成熟&#xff0c;厂商应结合自身需求&#xff0c;重新思考“基于开源自建数据平台”的重资产模式与“购买…

【AMBA Bus ACE 总线 7.1 -- ACE Domains 介绍 2】

请阅读【AMBA Bus ACE 总线与Cache 专栏 】 欢迎学习:【嵌入式开发学习必备专栏】 文章目录 AxDOMAINAxDOMAIN[1:0]的值及含义AxDOMAIN 在ARM的AXI Coherency Extensions (ACE) 协议中,AxDOMAIN[1:0]是一个重要的信号字段,用于指示传输的域类型。这个字段影响了传输对系统…

Spring Boot支持发送邮件

GitHub&#xff1a;SpringBootDemo Gitee&#xff1a;SpringBootDemo 微信公众号&#xff1a; 通过Spring Boot整合邮件任务&#xff0c;支持发送邮件&#xff0c;可以实现服务故障时向指定邮箱发送邮件。 0 开发环境 JDK&#xff1a;1.8Spring Boot&#xff1a;2.7.18 1…

花了24小时做的采购、库存、进销存excel模板,真心好用,免费分享

花了24小时做的采购、库存、进销存excel模板&#xff0c;真心好用 在企业的日常运营中&#xff0c;进销存管理是一项至关重要的任务。它不仅涉及到商品的采购、销售和库存管理&#xff0c;还直接影响到企业的财务状况和市场竞争力。为了提高管理效率&#xff0c;许多企业选择使…

传感网应用开发教程--AT指令访问新大陆云平台(ESP8266模块+物联网云+TCP)

实现目标 1、熟悉AT指令 2、熟悉新大陆云平台新建项目 3、具体目标&#xff1a;&#xff08;1&#xff09;注册新大陆云平台&#xff1b;&#xff08;2&#xff09;新建一个联网方案为WIFI的项目&#xff1b;&#xff08;3&#xff09;ESP8266模块&#xff0c;通过AT指令访问…

经典笔试题:快速排序 计数排序

Problem: 912. 排序数组 思路 &#x1f468;‍&#x1f3eb; 三叶题解 &#x1f496; AC&#xff1a;计数排序 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) class Solution {public int[] sortArray(int[] nums) {int max -50001, min 50001;for (…

HCIP的学习(15)

第六章&#xff0c;BGP—边界网关协议 自治系统—AS ​ 定义&#xff1a;由一个单一的机构或组织所管理的一系列IP网络及其设备所构成的集合。 ​ AS的来源&#xff1a; 整个网络规模过大&#xff0c;会导致路由信息收敛速度过慢&#xff0c;设备对相同目标认知不同。AS之间…

MATLAB实现遗传算法优化选址-路径LRP问题(Location-Routing Problem)

MATLAB实现遗传算法优化选址-路径LRP问题(Location-Routing Problem) 一、模型 选址车辆路径问题&#xff08;Location-Routing Problem, LRP&#xff09;是一个组合优化问题&#xff0c;旨在同时优化设施位置的选择和车辆的配送路径。在这个问题中&#xff0c;我们考虑一个由…

栈与队列的实现

前言 本次博客将要实现一下栈和队列&#xff0c;好吧 他们两个既可以使用动态数组也可以使用链表来实现 本次会有详细的讲解 栈的实现 栈的基础知识 什么是栈呢&#xff1f; 栈的性质是后进先出 来画个图来理解 当然可不可以出一个进一个呢&#xff0c;当然可以了 比如…

C++笔记(STL标准库)

1.STL六大部件 容器 Containers分配器 Allocators&#xff1a;帮容器分配内存算法 Algorithms迭代器 Iterators&#xff1a;算法通过迭代器操作容器里的数据&#xff0c;是一种泛化的指针适配器 Adapters&#xff1a;修改或扩展已有类或函数的接口以满足特定的需求仿函数 Func…

Python深度学习基于Tensorflow(9)注意力机制

文章目录 注意力机制是怎么工作的注意力机制的类型 构建Transformer模型Embedding层注意力机制的实现Encoder实现Decoder实现Transformer实现 注意力机制的主要思想是将注意力集中在信息的重要部分&#xff0c;对重要部分投入更多的资源&#xff0c;以获取更多所关注目标的细节…

2024最新商业视频打赏系统源码 多套模板 有代理后台 已对接支付

简介&#xff1a; 2024最新商业视频打赏系统源码 多套模板 有代理后台 已对接支付 图片&#xff1a; 源码下载

清华发布Temporal Scaling Law,解释时间尺度对大模型表现的影响

众所周知&#xff0c; 语言模型调参&#xff01; 预训练语言模型调参&#xff01;&#xff01; 预训练大语言模型调参&#xff01;&#xff01;&#xff01; 简直就是一个指数级递增令人炸毛的事情&#xff0c;小编也常常在做梦&#xff0c;要是只训练几步就知道现在的超参…

【优选算法】—Leetcode—11—— 盛最多水的容器

1.题目 11. 盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#…

K邻近算法

简介 介绍了非常简单的算法&#xff1a;K邻近算法&#xff0c;即KNN。 基本介绍 K-近邻算法&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;是一种基本且广泛应用的监督学习算法&#xff0c;主要用于分类和回归任务。 工作原理非常简答直观&#xff1a;所谓…