`

Mysql优化(深入浅出mysql数据库开发阅读笔记)

 
阅读更多
《深入浅出Mysql数据库开发、优化与管理维护》笔记
1、优化sql的一般步骤
  1.1 使用 show status 命令了解各种sql的执行频率
      进入mysql控制台执行
        show session status 查询当前连接的统计结果
        show global status 查询自数据库上次启动至今的统计结果

      或者在操作系统的终端执行
        mysqladmin extended-status
     
      可以通过like语句来查询一些特定的内容
      比如 show global status like "Com_%";就查看上次启动以来的每个Com_xxx语句执行的次数
     Com_select: 执行select查询的次数
     Com_insert: 执行insert的次数
     Com_update: 执行update的次数
     Com_delete: 执行delete的次数

     这些参数会都mysql所有存储引擎的表操作都做记录
     另外还有专门针对某一些存储引擎的,比如:
     Innodb_rows_read
     Innodb_rows_insert
     Innodb_rows_update
     Innobd_rows_delete

     通过上面这些数据的比较可以判断数据库是写为主,还是查询为主

     关于事务的信息 可以通过 Com_commit 和 Com_rollback 来了解提交和回滚的情况。如果回滚操作非常的频繁,说明应用编写存在很大的问题
    
     另外几个比较重要的,可以展示数据库基本情况的句子:
     Connections: 试图连接Mysql数据库的次数
     Uptime: 服务器工作时间
     Slow_queries: 慢查询的次数


   1.2 定位执行效率比较低的sql语句
      有两种方法:
      一、通过慢查询日志来定位。用--log-slow-queries[=filename]选项启动时,mysqld写一个包含所有执行时间超过long_query_time秒得sql语句的日志文件
      二、使用show processlist命令查看当前MySQL在进行的线程,包括线程的状态,是否锁表等,可以实时的查看sql的执行情况,同时对一些锁表操作进行优化。

   1.3 通过Explain分析低效SQL的执行计划
       再通过上面步骤,查到低效率的sql语句之后,可以通过 explain和desc命令获取mysql如何执行select语句的信息,包括select执行过程中表如何连接和连接的顺序。
       比如
explain select * from sum(money) from sales a, company b where a.company_id = b.id and a.year = 2006
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
| id | select_type | table | type   | possible_keys | key  | key_len | ref  | rows | Extra               |
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
|  1 | SIMPLE      | user  | system | NULL          | NULL | NULL    | NULL |    0 | const row not found |
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
1 row in set (0.00 sec)


       这个显示的结果是横向的,不够友好,在后面 追加参数“\G”可以每一项一列信息的显示
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: user
         type: system
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 0
        Extra: const row not found
1 row in set (0.00 sec)

ERROR:
No query specified

上面每一列的含义说明
   select_type: 表示select的类型(SIMPLE=>简单表,不使用表连接或者子查询,PRIMARY=>主查询,外层的查询,UNION=>UNION中的第二个或者后面的查询语句,SUBQUERY=>子查询中的第一个select)
   table; 输出结果集的表
   possible_keys: 表示查询时,可能使用的索引
   key: 表示实际使用的索引
   key_len: 索引字段的长度
   rows; 扫描的行的数量
   Extra: 执行情况的说明和描述
   type: 表示表的连接类型,性能有好到差的链接类型为:
      system=>只有一行,也就是常量表,
      const=>单表中最多有一个匹配行,例如primary key或者unique index,
      eq_ref=>对于前面的每一行,在此表中只查询一条记录,简单来说,就是多表连接中使用primary key或者unique index, 
      ref=>与eq_ref类似,区别在于不是使用primay key或者unique index而是使用普通的索引,
      ref_or_null=>与ref类似,区别在于条件中包含对null的查询,
      index_merge=>索引合并优化,
      unique_subquery=>in的后面是一个查询主键字段的子查询,
      index_subquery=>与unique_subquery类似,区别在于in的后面是查询非唯一索引字段的子查询,
      range=>单表中的查询范围,
      index=>对于前面的每一行,都通过查询索引来得到数据,
      all=>对于前面的每一行,都通过全表扫描来得到数据


   
2 索引问题
  2.1 索引的存储分类
     MyISAM存储索引的表的数据和索引是自动分开存储的,各自是独立的文件
     InnoDB存储引擎的表的数据和索引是存储在同一个表的空间里面,但是可以有多个文件组成
     Mysql中的存储类型木匾只有两种,BTREE和HASH,具体情况和表的存储引擎有关。
     MyISAM和InnoDb存储引擎都支持BTREE索引,
     MEMORY/HEAP存储引擎可以支持HASH和BTREE索引
    
     mysql不支持函数索引,但是能对队列的前面的某一部分进行索引,例如name字段,可以只取name的前四个字符来进行索引。

2.2 使用索引
     对相关列使用索引是提高select性能的最佳途径
     使用索引的条件:a、查询条件中有索引关键字,b、多列索引只有查询条件使用了多列关键字最左边的前缀时,才可以使用索引,否则将不能使用索引。
    2.2.1 使用索引
     一下情况中会使用到索引:
     (1) 多列索引,只要查询的条件中用到了最左边的列,索引一般就会被使用
     (2) 对于使用like查询,后面如果是常量,只有%号不在第一个字符时,索引才可能被用到 比如 like "%3" 不会用索引, like "3%"就会走索引
     (3) 对大文本进行搜索的时候,使用全文索引,而不是使用 like '%...%'
     (4) 如果列名是索引,使用column_name is null将使用索引,
      例如: select * from aaa where name is null(name是索引列)
    2.2.2 存在索引但不使用索引
      在下列情况下,虽然mysql存在索引,但是并不会使用到索引
     (1)如果Mysql估计使用索引比全表扫描更慢,则不使用索引。例如如果列key_1 均匀分布在1和100之间,那么查询 select * from table where key_1 > 1 and key_1 < 90;
     (2)如果使用MEMPRY/HEAP表并且,where条件中不使用“=”进行索引列,那么不会用到索引。heap表只有在使用“=”的时候,才使用索引
     (3)用or隔开的条件,如果or前面的列中有索引,而后面的列中没有索引,那么涉及的索引都不会被用到(or中有一个条件中的列没有索引就用不到索引)
     (4)如果不是索引列的第一部分(复合索引的第一部分)
     (5)如果like是%开始的
     (6)如果列类型是字符串,那么一定记得在where条件中把字符常量值用引号引起来,否则即便是这个列上有索引,也不用用到(比如name字段是字符串的,却写了name=123。要改成“123”)
    
   2.3 查看索引使用情况
    如果索引正在工作,Handler_read_key的值将很高,这个值代表了一个行被索引值读的次数,很低得知表明增加索引得到的性能改善不高
    Handler_read_rnd_next的值高则意味着查询的效率低效,并且应该建立索引补救。它的含义是:数据文件中读下一行的请求数。如果正在进行大量的表扫描,Handle_read_rnd_next的值较高,则通常说明表索引不正确或者写入的查询没有利用索引
    查看方法:show status like 'Handler_read%'

3 简单的优化方法
   3.1 定期分析表和检查表
   分析表的语法:
   analyze [local | no_write_to_binlog] table tab1_name [, ta1_name] ...
   用于分析和存储表的关键字分布
   分析结果可以使得系统得到更准确地统计信息,使得sql能够正确的执行计划。
   如果用户感觉实际执行计划并不是与预期的执行计划,执行一次分析表可能会解决问题。
   在分析期间,使用一个读取锁对表进行锁定,这对于MyISAM,BDB和InnoDb表有作用。对于MyISAM表,与使用myisamchk -a 相当
   例如:
   analyze table user;
mysql> analyze table user;
+------------+---------+----------+----------+
| Table      | Op      | Msg_type | Msg_text |
+------------+---------+----------+----------+
| mysql.user | analyze | status   | OK       |
+------------+---------+----------+----------+
1 row in set (0.05 sec)


   检查表的语法如下:
   check table tab1_name [,tab1_name] ... [option] .. option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
   作用是:检查一个或者多个表中是否有错误。他对MyISAM和InnoDB表有作用,对于MyISAM表,关键字统计数据被更新。例如:
  check table user;
mysql> check table user;
+------------+-------+----------+----------+
| Table      | Op    | Msg_type | Msg_text |
+------------+-------+----------+----------+
| mysql.user | check | status   | OK       |
+------------+-------+----------+----------+
1 row in set (0.00 sec)


  check table也可以检查视图是否有错误,例如:在视图定义中被引用的表不存在

3.2 定期优化表
    语法:
    optimize [local | no_write_to_binlog] table tab1_name [, tab1_name] ...
    适用范围:
    a、删除了表的一部分
    b、对含有可变长度行的表(varchar,blob,text列的表)进行了很多更改。
    这个命令可以将表中的空间碎片进行合并,并且可以消除由于删除或者更新造成的空间浪费。但是这个命令只对MyISAM,BDB和InnoDb表起作用
mysql> optimize table user;
+------------+----------+----------+----------+
| Table      | Op       | Msg_type | Msg_text |
+------------+----------+----------+----------+
| mysql.user | optimize | status   | OK       |
+------------+----------+----------+----------+
1 row in set (0.01 sec)


4 常用SQL的优化
  4.1 大批量插入数据
    当用load命令导入数据的时候,适当的设置可以提高导入的速度
    4.1.1 对于MyISAM存储引擎的表方法如下:
    alter table tab_name disable keys;
    load the data
    alter table tab_name enable keys;

    上面操作是打开或者关闭MyISAM表不是唯一索引的更新
    ps:导入非空数据表的时候,上面方法很有效,但是导入空表的时候,索引是数据导入完毕之后才去创建的,所以没有影响
    4.2.2 对InnoDB表的数据导入
     (1)InnoDB类型的表是按照主键的顺序来存储的,所以导入数据按照主键的顺序排列,可以有效的提高导入的效率
     (2)在导入数据之前,关闭唯一性校验,set unique_checks=0 ,在导入结束之后设置为 1 开启唯一性校验,可以提高导入效率
     (3)如果应用使用自动提交的方式,建议在导入数据的时候执行 set autocomment=0,关闭自动提交,导入结束之后再设置为1,打开自动提交

  4.2 优化insert语句
     (1)如果是从同一客户那里插入很多航,尽量使用多个值表的insert语句,这种方式将大大的缩短客户端与数据库之间的链接,关闭等资源的消耗,使得效率比分开执行的单个insert语句快
     例如:insert to test values(1,2),(1,3),(1,4)....
     (2)如果从不同的客户中杀入多行,能通过使用insert delayed语句得到更高的速度。delayed是让insert语句立马执行,四十数据都被放在内存的队列中,并没有真正的写入磁盘,这比每一条数据分别插入快得多。low_priority 刚好想法,是所有其他用户对表的读写完成后才进行插入
     (3)将索引文件和数据文件分在不同的磁盘上存放
     (4)如果进行批量插入可以增加 bulk_insert_buffer_size 变量值的方法来提高速度,但是这只能对MyIsAM表使用
     (5)当一个文本文件装载一个表时,使用 load file insert。这比通常的sql语句快20倍
4.3 优化group by语句
     如果查询包括group by但是用户想避免白须结果的小号,可以指定order by null禁止排序
   例如:
   select id, sum(money) from sale2 group by id order by null

4.4 优化order by语句
    可以使用索引来满足一个order by语句
    条件:
    where条件和order by使用相同的索引,并且order by的顺序和索引顺序相同,并且order by的字段都是升序或者降序
    比如: order by key1,key2
           where key1=123 order by key1 desc, key2 desc
           order by key1 desc, key2 desc

    但是以下情况不可以
       order by key1 asc, key2 desc 混合使用ASC和DESC
       where key2 = 1 , order by key1 查询的关键字和排序的不一样
       order by key1,key2 对不同的关键字使用排序

   
4.5 优化嵌套查询
     有些情况下,子查询可以被更加有效的join查询代替
     比如 select * from a where b_id not in(select id from b) 
     换成 select * from a left join b on a.b_id = b.id where a.b_id is not null


  4.6 优化OR条件
      or的每一个条件都使用索引
      但是如果or的几个条件正好是复合索引的元素,则不能起到加速的效果
   4.7 使用SQL提示
      在sql中加入一些人为的提示来达到优化操作的目的
      例如:
      select sql_buffer_results * from
      这个语句将强行MySql生成一个临时的结果集,只要临时结果集生成之后,所有表上的锁都会被释放。
      这能解决遇到表锁问题时,或者要花长时间将结果传给客户端时有所帮助,因为这样可以尽快的释放资源

      (1)use index
      在查询语句中表名的后面,添加use index来提供希望mysql去参考的索引列表,就可以让mysql不再考虑其他可用的索引
      select * from a use index(ind_a_id) where id = 1

      (2)ignore index
      如果用户只是单纯的想让mysql忽略一个多个索引,则可以使用ignore index作为hint
       select * from a ignore index(ind_a_id) where id = 1

      (3)force index
      强制MySQL使用一个特定的索引,可在查询中使用


      
分享到:
评论

相关推荐

    《MYSQL必知必会》读书笔记

    《MYSQL必知必会》是一本深入浅出介绍MySQL的书籍,旨在帮助读者掌握MySQL的基础知识和高级特性。以下是对这本书中核心知识点的详细解析: 1. **SQL语言基础**: SQL(Structured Query Language)是用于管理关系...

    OA开发手记

    【OA开发手记】是关于企业办公自动化(Office Automation,简称OA)系统开发的经验与笔记,博主通过分享自己的实践过程,深入浅出地探讨了OA系统的核心技术和开发流程。在这个过程中,源码和工具的使用是关键部分,...

    韩顺平各种课题笔记

    《韩顺平各种课题笔记》是一份集合了韩顺平老师深入浅出讲解的IT知识宝典。韩顺平老师在IT行业中具有广泛的影响力,以其深入、实用的教学风格深受学生和专业人士的喜爱。这些笔记经过精心筛选,确保每一份内容都包含...

    韩顺平php入门到精通笔记

    《韩顺平php入门到精通笔记》是一本深入浅出的PHP学习资料,它涵盖了从基础到高级的各种PHP编程知识,对于想要系统学习并掌握PHP技术的人来说,是一份极具价值的资源。以下将对这份笔记中的核心知识点进行详细阐述。...

    linux基础进阶笔记

    linux基础进阶笔记,配套视频:https://www.bilibili.com/list/474327672?sid=4493093&spm_id_from=333.999.0.0&desc=1

    IMG20241115211541.jpg

    IMG20241115211541.jpg

    Sen2_ARI_median.txt

    GEE训练教程——Landsat5、8和Sentinel-2、DEM和各2哦想指数下载

    毕业设计&课设_基于 flask-whoosh-jieba 的代码,涉及文件管理及问题修复.zip

    该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

    基于springboot家政预约平台源码数据库文档.zip

    基于springboot家政预约平台源码数据库文档.zip

    Ucharts添加stack和折线图line的混合图

    Ucharts添加stack和折线图line的混合图

    基于springboot员工在线餐饮管理系统源码数据库文档.zip

    基于springboot员工在线餐饮管理系统源码数据库文档.zip

    2015-2021年新能源汽车分地区、分类型、分级别销量逐月数据和进出口数据-最新出炉.zip

    新能源汽车进出口数据 1、时间跨度:2018-2020年 2、指标说明:包含如下指标的进出口数据:混合动力客车(10座及以上)、纯电动客车(10座及以上)、非插电式混合动力乘用车、插电式混合动力乘用车、纯电动乘用车 二、新能源汽车进出口月销售数据(分地区、分类型、分 级别) 1、数据来源:见资料内说明 2、时间跨度:2014年1月-2021年5月 4、指标说明: 包含如下指标 2015年1月-2021年5月新能源乘用车终端月度销量(分类型)部分内容如下: 新能源乘用车(单月值、累计值 )、插电式混合动力 月度销量合计(狭义乘用车轿车、SUV、MPV、交叉型乘用车); 月度销量同比增速(狭义乘用车轿车、SUV、MPV、交叉型乘用车); 累计销量合计(狭义乘用车轿车、SUV、IPV、交叉型乘用车); 累计销量同比增速(狭义乘用车轿车、SUV、MPV、交叉型乘用车); 累计结构变化(狭义乘用车轿车、SUV、IPV、交叉型乘用车); 2015年1月-2021年5月新能源乘用车终端月度销量(分地区)内容如下: 更多见资源内

    中心主题-241121215200.pdf

    中心主题-241121215200.pdf

    蓝奏云下载链接与密码整理

    内容概要:本文档提供了多个蓝奏云下载链接及其对应解压密码,帮助用户快速获取所需文件。 适合人群:需要从蓝奏云下载文件的互联网用户。 使用场景及目标:方便地记录并分享蓝奏云上文件的下载地址和密码,提高下载效率。 阅读建议:直接查看并使用提供的链接和密码即可。若遇到失效情况,请尝试联系上传者确认更新后的链接。

    Javaweb仓库管理系统项目源码.zip

    基于Java web 实现的仓库管理系统源码,适用于初学者了解Java web的开发过程以及仓库管理系统的实现。

    Python-文件重命名-自定义添加文字-重命名

    资源名称:Python-文件重命名-自定义添加文字-重命名 类型:windows—exe可执行工具 环境:Windows10或以上系统 功能: 1、点击按钮 "源原文"【浏览】表示:选择重命名的文件夹 2、点击按钮 "保存文件夹"【浏览】表示:保存的路径(为了方便可选择保存在 源文件中 ) 3、功能①:在【头部】添加自定义文字 4、功能②:在【尾部】添加自定义文字 5、功能③:输入源字符 ;输入替换字符 可以将源文件中的字符替换自定义的 6、功能④:自动加上编号_1 _2 _3 优点: 1、非常快的速度! 2、已打包—双击即用!无需安装! 3、自带GUI界面方便使用!

    JDK8安装包,为各位学习的朋友免费提供

    JDK8安装包

    Centos-7yum的rpm包

    配合作者 一同使用 作者地址没有次下载路径 https://blog.csdn.net/weixin_52372189/article/details/127471149?fromshare=blogdetail&sharetype=blogdetail&sharerId=127471149&sharerefer=PC&sharesource=weixin_45375332&sharefrom=from_link

    setup_python_geospatial_analysis.ipynb

    GEE训练教程

    毕业设计&课设_文成公主微信公众号全栈工程,含技术栈、架构及部署流程等内容.zip

    该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

Global site tag (gtag.js) - Google Analytics