Mysql索引介绍及使用注意事项,limit分页查询,慢查询分析

本文将从以下十二个方面进行介绍:

一、索引概念介绍
二、索引类型FULLTEXT,HASH,BTREE,RTREE有什么功能和性能上的不同呢?
三、各种索引类型的使用情况
四、索引种类(普通索引,唯一索引,主键索引,组合索引,全文索引,索引合并,覆盖索引)
五、索引操作:创建,删除,修改
六、创建索引的时机
七、命中索引
八、其它索引使用注意事项
九、LIMIT分页
十、使用explain 查看执行计划
十一、慢查询日志
十二、如何利用MySQL自带的慢查询日志分析工具mysqldumpslow分析日志?

一、索引概念介绍
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

如大家所知道的,Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。

二、索引类型有什么功能和性能上的不同呢?
Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。

1、FULLTEXT

即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE INDEX创建FULLTEXT索引,要比先为一张表建立FULLTEXT然后再将数据写入的速度快很多。

全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。在没有全文索引之前,这样一个查询语句是要进行遍历数据表操作的,可见,在数据量较大时是极其的耗时的,如果没有异步IO处理,进程将被挟持,很浪费时间,当然这里不对异步IO作进一步讲解,想了解的童鞋,自行谷哥。

全文索引的使用方法并不复杂:

创建ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`[,cname2…]);

使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) AGAINST ('word' MODE );

其中, MODE为搜寻方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。

关于这三种搜寻方式,愚安在这里也不多做交代,简单地说,就是,布尔模式,允许word里含一些特殊字符用于标记一些具体的要求,如+表示一定要有,-表示一定没有,*表示通用匹配符,是不是想起了正则,类似吧;自然语言模式,就是简单的单词匹配;含表达式的自然语言模式,就是先用自然语言模式处理,对返回的结果,再进行表达式匹配。

对搜索引擎稍微有点了解的同学,肯定知道分词这个概念,FULLTEXT索引也是按照分词原理建立索引的。西文中,大部分为字母文字,分词可以很方便的按照空格进行分割。但很明显,中文不能按照这种方式进行分词。那又怎么办呢?这个向大家介绍一个Mysql的中文分词插件Mysqlcft,有了它,就可以对中文进行分词,想了解的同学请移步Mysqlcft,当然还有其他的分词插件可以使用。

2、HASH

Hash这个词,可以说,自打我们开始码的那一天起,就开始不停地见到和使用到了。其实,hash就是一种(key=>value)形式的键值对,如数学中的函数映射,允许多个key对应相同的value,但不允许一个key对应多个value。正是由于这个特性,hash很适合做索引,为某一列或几列建立hash索引,就会利用这一列或几列的值通过一定的算法计算出一个hash值,对应一行或几行数据(这里在概念上和函数映射有区别,不要混淆)。在java语言中,每个类都有自己的hashcode()方法,没有显示定义的都继承自object类,该方法使得每一个对象都是唯一的,在进行对象间equal比较,和序列化传输中起到了很重要的作用。hash的生成方法有很多种,足可以保证hash码的唯一性,例如在MongoDB中,每一个document都有系统为其生成的唯一的objectID(包含时间戳,主机散列值,进程PID,和自增ID)也是一种hash的表现。额,我好像扯远了-_-!

由于hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。那为什么还需要其他的树形索引呢?

在这里愚安就不自己总结了。

(1)Hash 索引仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询。 
由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。 
(2)Hash 索引无法被用来避免数据的排序操作。 
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算; 
(3)Hash 索引不能利用部分索引键查询。 
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。 
(4)Hash 索引在任何时候都不能避免表扫描。 
前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。 
(5)Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。 
对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。

愚安我稍作补充,讲一下HASH索引的过程,顺便解释下上面的第4,5条:

当我们为某一列或某几列建立hash索引时(目前就只有MEMORY引擎显式地支持这种索引),会在硬盘上生成类似如下的文件:

hash值 

存储地址    

1db54bc745a1

77#45b5 

4bca452157d4

76#4556,77#45cc…

hash值即为通过特定算法由指定列数据计算出来,磁盘地址即为所在数据行存储在硬盘上的地址(也有可能是其他存储地址,其实MEMORY会将hash表导入内存)。

这样,当我们进行WHERE age = 18 时,会将18通过相同的算法计算出一个hash值==>在hash表中找到对应的储存地址==>根据存储地址取得数据。

所以,每次查询时都要遍历hash表,直到找到对应的hash值,如(4),数据量大了之后,hash表也会变得庞大起来,性能下降,遍历耗时增加,如(5)。

3、BTREE

BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中,相信学过数据结构的童鞋都对当初学习二叉树这种数据结构的经历记忆犹新,反正愚安我当时为了软考可是被这玩意儿好好地折腾了一番,不过那次考试好像没怎么考这个。如二叉树一样,每次查询都是从树的入口root开始,依次遍历node,获取leaf。

BTREE在MyISAM里的形式和Innodb稍有不同

在 Innodb里,有两种形态:一是primary key形态,其leaf node里存放的是数据,而且不仅存放了索引键的数据,还存放了其他字段的数据。二是secondary index,其leaf node和普通的BTREE差不多,只是还存放了指向主键的信息.

而在MyISAM里,主键和其他的并没有太大区别。不过和Innodb不太一样的地方是在MyISAM里,leaf node里存放的不是主键的信息,而是指向数据文件里的对应数据行的信息.

4、RTREE

RTREE在mysql很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。

相对于BTREE,RTREE的优势在于范围查找.

三、各种索引类型的使用情况

(1)对于BTREE这种Mysql默认的索引类型,具有普遍的适用性

(2)由于FULLTEXT对中文支持不是很好,在没有插件的情况下,最好不要使用。其实,一些小的博客应用,只需要在数据采集时,为其建立关键字列表,通过关键字索引,也是一个不错的方法,至少愚安我是经常这么做的。

(3)对于一些搜索引擎级别的应用来说,FULLTEXT同样不是一个好的处理方法,Mysql的全文索引建立的文件还是比较大的,而且效率不是很高,即便是使用了中文分词插件,对中文分词支持也只是一般。真要碰到这种问题,Apache的Lucene或许是你的选择。

(4)正是因为hash表在处理较小数据量时具有无可比拟的素的优势,所以hash索引很适合做缓存(内存数据库)。如mysql数据库的内存版本Memsql,使用量很广泛的缓存工具Mencached,NoSql数据库redis等,都使用了hash索引这种形式。当然,不想学习这些东西的话Mysql的MEMORY引擎也是可以满足这种需求的。

四、索引种类
普通索引:仅加速查询

唯一索引:加速查询 + 列值唯一(可以有null)

主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个

组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并

全文索引:对文本的内容进行分词,进行搜索

ps.

    索引合并,使用多个单列索引组合搜索
    覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖

五、操作索引
    1. 创建索引

--创建普通索引CREATE INDEX index_name ON table_name(col_name);--创建唯一索引CREATE UNIQUE INDEX index_name ON table_name(col_name);--创建普通组合索引CREATE INDEX index_name ON table_name(col_name_1,col_name_2);--创建唯一组合索引CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);
    2. 通过修改表结构创建索引

ALTER TABLE table_name ADD INDEX index_name(col_name);
   3. 创建表时直接指定索引

CREATE TABLE table_name (ID INT NOT NULL,col_name VARCHAR (16) NOT NULL,INDEX index_name (col_name));
  4. 删除索引
--直接删除索引DROP INDEX index_name ON table_name;--修改表结构删除索引ALTER TABLE table_name DROP INDEX index_name;
 5. 其它相关命令

- 查看表结构
     desc table_name;
  - 查看生成表的SQL
     show create table table_name;
  - 查看索引
     show index from  table_name;
  - 查看执行时间
     set profiling = 1;
     SQL...
     show profiles;mysql> set profiling = 1;
 Query OK, 0 rows affected, 1 warning (0.00 sec)mysql> select * from gyl1;
 Empty set (0.00 sec)mysql> show profiles;
 +----------+------------+---------------------+
 | Query_ID | Duration   | Query               |
 +----------+------------+---------------------+
 |        1 | 0.00006400 |  set profiling = 1  |
 |        2 | 0.00013500 | set profiling = 1   |
 |        3 | 0.00021300 | select * from gyl1  |
 +----------+------------+---------------------+
 3 rows in set, 1 warning (0.00 sec)

六、创建索引的时机
到这里我们已经学会了建立索引,那么我们需要在什么情况下建立索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,因为MySQL只对<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引。例如:

SELECT t.Name  FROM mytable_t LEFT JOIN mytable_m ON t.Name=m.username WHERE m.age=20 AND m.city='郑州' ;
此时就需要对city和age建立索引,由于mytable_m表的userame也出现在了JOIN子句中,也有对它建立索引的必要。

刚才提到只有某些时候的LIKE才需建立索引。因为在以通配符%和_开头作查询时,MySQL不会使用索引。

七、命中索引
数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。
即使建立索引,索引也不会生效:

- like '%xx'   

     select * from tb1 where name like '%cn';- 使用函数
    select * from tb1 where reverse(name) = 'wupeiqi';

     - or    select * from tb1 where nid = 1 or email = 'seven@live.com';
    特别的:当or条件中有未建立索引的列才失效,以下会走索引
            select * from tb1 where nid = 1 or name = 'seven';
            select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'- 类型不一致
    如果列是字符串类型,传入条件是必须用引号引起来,不然...
     select * from tb1 where name = 999;

     - !=    select * from tb1 where name != 'alex'    特别的:如果是主键,则还是会走索引
     select * from tb1 where nid != 123

     - >    select * from tb1 where name > 'alex'    特别的:如果是主键或索引是整数类型,则还是会走索引
             select * from tb1 where nid > 123      

         select * from tb1 where num > 123- order by    select email from tb1 order by name desc;
    当根据索引排序时候,选择的映射如果不是索引,则不走索引
    特别的:如果对主键排序,则还是走索引:

        select * from tb1 order by nid desc;
 - 组合索引最左前缀
    如果组合索引为:(name,email)
    name and email       -- 使用索引    name                 -- 使用索引    email                -- 不使用索引

八、其它索引使用注意事项

- 避免使用select *   - count(1)或count(列) 代替 count(*)

- 创建表时尽量时 char 代替 varchar

- 表的字段顺序固定长度的字段优先

- 组合索引代替多个单列索引(经常使用多个条件查询时)

- 尽量使用短索引

- 使用连接(JOIN)来代替子查询(Sub-Queries)

- 连表时注意条件类型需一致- 索引散列值(重复多)不适合建索引,例:性别不适合

九、LIMIT分页

若需求是每页显示10条数据,如何建立分页?

我们可以先使用LIMIT尝试:
--第一页SELECT * FROM table_name LIMIT 0,10;

--第二页SELECT * FROM table_name LIMIT 10,10;

--第三页SELECT * FROM table_name LIMIT 20,10;
但是这样做有如下弊端:

每一条select语句都会从1遍历至当前位置,若跳转到第100页,则会遍历1000条记录

若记录的id不连续,则会出错

改善:

若已知每页的max_id和min_id,则可以通过主键索引来快速定位:
--下一页SELECT * FROM table_name WHERE id in (SELECT id FROM table_name WHERE id > max_id LIMIT 10);

--上一页SELECT * FROM table_name WHERE id in (SELECT id FROM table_name WHERE id < min_id ORDER BY id DESC LIMIT 10);

--当前页之后的某一页SELECT * FROM table_name WHERE id in (SELECT id FROM (SELECT id FROM (SELECT id FROM table_name WHERE id < min_id ORDER BY id desc LIMIT (页数差*10)) AS N ORDER BY N.id ASC LIMIT 10) AS P ORDER BY P.id ASC);

--当前页之前的某一页SELECT * FROM table_name WHERE id in (SELECT id FROM (SELECT id FROM (SELECT id FROM table_name WHERE id > max_id LIMIT (页数差*10)) AS N ORDER BY N.id DESC LIMIT 10) AS P) ORDER BY id ASC;

十、使用explain 查看执行计划

explain + 查询SQL - 用于显示SQL执行信息参数,根据参考信息可以进行SQL优化

mysql> explain select * from gyl1;
 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
 | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
 |  1 | SIMPLE      | gyl1  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
 1 row in set, 1 warning (0.00 sec)

id查询顺序标识

alter table tk_question_ls add key(difficulty);

KEY `difficulty` (`difficulty`)

如 explain select * from (select que_id,root_id  from tk_question_ls where difficulty < 3)  B;

索引是时间进行范围查询走了全表_索引类型

特别的:如果使用union连接其值可能为null

  •     select_type

        查询类型
            SIMPLE          简单查询PRIMARY         最外层查询
            SUBQUERY        映射为子查询
            DERIVED         子查询UNION           联合UNION RESULT    使用联合的结果
            ...table正在访问的表名

  •     type

        查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/constALL          

        全表扫描,对于数据表从头到尾找一遍select * from tb1;
                            特别的:如果有limit限制,则找到之后就不再继续向下扫描                                  
                   select * from tb1 where email = 'seven@live.com'   
                   select * from tb1 where email = 'seven@live.com' limit 1;
                            虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。 

            INDEX           全索引扫描,对索引从头到尾找一遍select nid from tb1;
            RANGE          对索引列进行范围查找select *  from tb1 where name < 'alex';
                            PS:between andin>   >=  <   <=  操作
                                注意:!= 和 > 符号
            INDEX_MERGE     合并索引,使用多个单列索引搜索select *  from tb1 where name = 'alex' or nid in (11,22,33);
            REF             根据索引查找一个或多个值select *  from tb1 where name = 'seven';
            EQ_REF      连接时使用primary key 或 unique类型select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid; 
            CONST        常量
                            表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。select nid from tb1 where nid = 2 ;
            SYSTEM          系统
                      表仅有一行(=系统表)。这是const联接类型的一个特例。select * from (select nid from tb1 where nid = 1) as A;

  •     possible_keys

          可能使用的索引key真实使用的

  •     key_len

        MySQL中使用索引字节长度

  •     rows

        mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值

  • extra

        该列包含MySQL解决查询的详细信息
        “Using index”
            此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
        “Using where”
            这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
        “Using temporary”
            这意味着mysql在对查询结果排序时会使用一个临时表。
        “Using filesort”
            这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
        “Range checked for each record(index map: N)”
            这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。

十一、慢查询日志

MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10S以上的语句。默认情况下,MySQLl数据库并不启动慢查询日志,需要我们手动来设置这个参数,当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件,也支持将日志记录写入数据库表。

1. 查看慢日志参数:
--查询配置命令

show variables like '%query%';           --当前配置参数
+------------------------------+--------------------------------------------------------+
 | Variable_name                | Value                                                  |
 +------------------------------+--------------------------------------------------------+
 | binlog_rows_query_log_events | OFF                                                    |
 | ft_query_expansion_limit     | 20                                                     |
 | have_query_cache             | YES        --时间限制,超过此时间,则记录                                            |
 | long_query_time              | 10.000000                                              |
 | query_alloc_block_size       | 8192                                                   |
 | query_cache_limit            | 1048576                                                |
 | query_cache_min_res_unit     | 4096                                                   |
 | query_cache_size             | 1048576                                                |
 | query_cache_type             | OFF                                                    |
 | query_cache_wlock_invalidate | OFF                                                    |
 | query_prealloc_size          | 8192    --是否开启慢日志记录                 |
 | slow_query_log               | OFF    --日志文件                                                |
 | slow_query_log_file          | /usr/local/mysql/data/yaoyingzhedeMacBook-Pro-slow.log |
 +------------------------------+--------------------------------------------------------+

slow log的日志相关参数详解

slow_query_log :是否开启慢查询日志,1表示开启,0表示关闭。

log-slow-queries :旧版(5.6以下版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log

slow-query-log-file:新版(5.6及以上版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log

long_query_time :慢查询阈值,当查询时间多于设定的阈值时,记录日志。

log_queries_not_using_indexes:未使用索引的查询也被记录到慢查询日志中(可选项)。

log_output:日志存储方式。log_output='FILE'表示将日志存入文件,默认值是'FILE'。log_output='TABLE'表示将日志存入数据库,这样日志信息就会被写入到mysql.slow_log表中。MySQL数据库支持同时两种日志存储方式,配置的时候以逗号隔开即可,如:log_output='FILE,TABLE'。日志记录到系统的专用日志表中,要比记录到文件耗费更多的系统资源,因此对于需要启用慢查询日志,又需要能够获得更高的系统性能,那么建议优先记录到文件。

2. 修改当前配置
set global 变量名 = 值;

--例如,修改时间限制为20

set long_query_time = 20;
ps.也可以直接打开慢日志配置文件进行修改,但必须重启服务才能生效

3. 查看MySQL慢日志

bogon:~ a6$ sudo more  /usr/local/mysql/data/yaoyingzhedeMacBook-Pro-slow.log
 /usr/local/mysql/bin/mysqld, Version: 5.7.19 (MySQL Community Server (GPL)). started with:
 Tcp port: 3306  Unix socket: /tmp/mysql.sock
 Time                 Id Command    Argument
 # Time: 2019-03-16T11:52:28.834505Z
 # User@Host: root[root] @ localhost []  Id:     4
 # Query_time: 0.002931  Lock_time: 0.000340 Rows_sent: 0  Rows_examined: 0
 use test_yyz;
 SET timestamp=1552737148;
 select * from one_and_two_kn_accumulate_stars;
 # Time: 2019-03-16T11:52:39.813257Z
 # User@Host: root[root] @ localhost []  Id:     4
 # Query_time: 0.032921  Lock_time: 0.000256 Rows_sent: 1575  Rows_examined: 1575
 SET timestamp=1552737159;
 select * from tk_question_ls;
 # Time: 2019-03-16T11:55:08.673479Z
 # User@Host: root[root] @ localhost []  Id:     4
 # Query_time: 0.018845  Lock_time: 0.000105 Rows_sent: 1575  Rows_examined: 1575
 SET timestamp=1552737308;
 select * from tk_question_ls;
 # Time: 2019-03-16T11:57:01.227570Z
 # User@Host: root[root] @ localhost []  Id:     4
 # Query_time: 0.020023  Lock_time: 0.019625 Rows_sent: 10  Rows_examined: 10
 SET timestamp=1552737421;
 select * from mysql.general_log;

十二、如何利用MySQL自带的慢查询日志分析工具mysqldumpslow分析日志?

bogon:~ a6$ sudo mysqldumpslow -s c -t 10  /usr/local/mysql/data/yaoyingzhedeMacBook-Pro-slow.log;

Reading mysql slow query log from /usr/local/mysql/data/yaoyingzhedeMacBook-Pro-slow.log
 Count: 2  Time=0.03s (0s)  Lock=0.00s (0s)  Rows=1575.0 (3150), root[root]@localhost
   select * from tk_question_ls
Count: 1  Time=0.00s (0s)  Lock=0.02s (0s)  Rows=10.0 (10), root[root]@localhost
   select * from mysql.general_log
Count: 1  Time=0.00s (0s)  Lock=0.00s (0s)  Rows=0.0 (0), root[root]@localhost
   select * from one_and_two_kn_accumulate_stars
Died at /usr/local/mysql/bin/mysqldumpslow line 161, <> chunk 4.

mysqldumpslow命令参数介绍:

bogon:~ a6$ mysqldumpslow -h
Option h requires an argument
ERROR: bad option

Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]

Parse and summarize the MySQL slow query log. Options are

--verbose    版本--debug      调试--help       帮助 -v           版本-d           调试模式-s ORDER     排序方式

  --verbose    verbose
  --debug      debug
  --help       write this text to standard output

  -v           verbose
  -d           debug
  -s ORDER     what to sort by (al, at, ar, c, l, r, t), 'at' is default
                al: average lock time
                ar: average rows sent
                at: average query time
                 c: count
                 l: lock time
                 r: rows sent
                 t: query time   
 
  -r           reverse the sort order (largest last instead of first)   反转顺序,默认文件倒序拍。
  -t NUM       just show the top n queries  显示前N条
  -a           don't abstract all numbers to N and strings to 'S'   不要将SQL中数字转换成N,字符串转换成S
  -n NUM       abstract numbers with at least n digits within names
  -g PATTERN   grep: only consider stmts that include this string 
正则匹配;
  -h HOSTNAME  hostname of db server for *-slow.log filename (can be wildcard),    mysql机器名或者IP;
               default is '*', i.e. match all
  -i NAME      name of server instance (if using mysql.server startup script)
  -l           don't subtract lock time from total time  
总时间中不减去锁定时间;