当前位置:首页 > 开发 > 数据库 > 正文

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

发表于: 2013-03-11   作者:hotsunshine   来源:转载   浏览次数:
摘要: 《深入浅出Mysql数据库开发、优化与管理维护》笔记 1、优化sql的一般步骤   1.1 使用 show status 命令了解各种sql的执行频率       进入mysql控制台执行 show session status 查询当前连接的统计结果 show global sta
《深入浅出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数据库开发阅读笔记)

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
项目开发初期,数据库数据比较单纯。许多开发人员,只要功能上实现了,就以为大吉。到了大量数据测试
开启定时任务 SHOW VARIABLES LIKE 'event%'; -- 查看定时任务是否开启(off:关闭 on:开启) set
0. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而
11.5.2 MySQL数据库的优化 很多接触过MySQL数据库的用户都知道MySQL数据库的优化可以通过修改配置参
出错记录: 1、mysql服务启动不了,进程意外终止 1067 错误显示:can not connect to mysql server
【维护和优化的工作】 ① 维护数据字典 ② 维护索引 ③ 维护表结构 ④ 在适当的时候对表进行水平拆
MYSQL数据库优化方向 sql及索引优化,存储优化(程序) 数据库表结构优化 系统配置 硬件 一、SQL语
本篇文章是对mysql数据库优化进行了详细的总结与介绍,需要的朋友参考一下 1. 优化你的MySQL查询缓
1. 优化你的MySQL查询缓存 在MySQL服务器上进行查询,可以启用高速查询缓存。让数据库引擎在后台悄
对于一个以数据为中心的应用,数据库的好坏直接影响到程序的性能,因此数据库性能至关重要。一般来
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号