慢查询排查

        show status;  // 查询mysql数据库的一些运行状态
        show status like 'uptime'; // 查看mysql数据库启动多长时间,myisam存储引擎长时间启动需要进行碎片整理
 
        查看慢查询
        show status like 'slow_queries';
 
        查询慢查询时间
        show variables like 'long_query_time';
 
        设置慢查询时间 
        set long_query_time = 0.5;
 

分析执行情况 EXPLAIN详解
 
        分析查询语句的执行情况,可以分析出所查询的表的一些特征
        EXPLAIN/DESCRIBE/DESCSELECT * FROM...;
 
        
 
 

每个字段说明:

 
 
 

id:SELECT标识符。这是SELECT的查询序列号。

 
select_type:表示SELECT语句的类型。它可以是以下几种取值:
    SIMPLE:表示简单杳询,其中不包括连接查询和子查询;
    PRIMARY:表示主查询,或者最外层的查询语句;
    UNION:表示连接查询的第2个或后面的查询语句;
    DEPENDENT UNION:连接查询中的第2个或后面的SELECT语句,取决于外面的查询;
    UNION RESULT:连接查询的结果;
    SUBQUERY:子查询中的第一个SELECT语句;
    DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询;
    DERIVED:导出表的SELECT (FROM语句的子查询)。
 
table:表示查询的表。
 
type:表示表的连接类型。下面按照从最佳类型到最差类型的顺序给出各种连接类型:
 
    (1) system
        该表仅有一行的系统表。这是const连接类型的一个特例。
 
    (2) const

数据表最多只有一个匹配行,它将在查询开始时被读取,并在余下的査询优化中作为常量对待。const表查询速度很快,因为它们只读取一次。const用于使用常数值比较PRIMARY KEY或UNIQUE索引的所有部分的场合。

        在下面查询中,tb1_name可用const表:
        SELECT  *  from tb1_name WHERE primary_key=1;
        SELECT * from tb1_name WHERE primary_key_part1=1 AND primary_key_part2=2
 
    (3) eq_ref
        对于每个来自前面的表的行组合,从该表中读取一行。当一个索引的所有部分都在查询中使用,并且索引是UNIQUE或者PRIMARY KEY时,即可使用这种类型。
        eq_ref可以用于使用“=”操作符比较带索引的列。比较值可以为常量或者一个在该表前面所读取的表的列的表达式。
        在下面例子中,MySQL可以使用eq_ref来处理ref_tables:
        SELECT * FROM ref_table,other_table WHERE ref_table.key_cloumn = other_table.cloumn;
        SELECT * FROM ref_table, other_tbale WHERE ref_table.key_cloumn_part1 = other_table.cloumn AND ref_table.key_cloumn_part2 = 1;
 
    (4)ref
        对于来自前面的表的任意组合,将从该表中读取所有匹配的行。这种类型用于索引既不是UNIQUE也不是PRIMARY KEY的情况,或者查询中使用了索引列在左子集,既索引中左边的部分列组合。ref可以用于使用=或者<=>操作符的带索引的列。
        以下的几个例子中,mysql将使用 ref 来处理ref_table:   
        select * from ref_table where key_column=expr; 
        select * from ref_table,other_table where ref_table.key_column=other_table.column; 
        select * from ref_table,other_table where ref_table.key_column_part1=other_table.column and ref_table.key_column_part2=1;
 
    (5)ref_or_null
        这种连接类型类似ref,不同的是mysql会在检索的时候额外的搜索包含null值的记录。在解决子查询中经常使用该链接类型的优化。
        在以下的例子中,mysql使用ref_or_null 类型来处理 ref_table:
        select * from ref_table where key_column=expr or key_column is null;
 
    (6)index_merge
        该链接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。
 
    (7)unique_subquery
        该类型替换了下面形式的IN子查询的ref:
        value in (select primary_key from single_table where some_expr)
 
    (8)index_subquery
        这种连接类型类似 unique_subquery。可以替换IN子查询,不过它用于在子查询中没有唯一索引的情况下,
        例如以下形式:
        value in (select key_column from single_table where some_expr)
 
    (9)range
        只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。ken_len包含所使用索引的最长关键元素。当使用 =, <>, >,>=, <, <=, is null, <=>, between, 或 in操作符,用常量比较关键字列时,类型为range。
        下面介绍几种检索制定行的情况:
        select * from tbl_name where key_column = 10; 
        select * from tbl_name where key_column between 10 and 20; 
        select * from tbl_name where key_column in (10,20,30); 
        select * from tbl_name where key_part1= 10 and key_part2 in (10,20,30);
 
    (10)index
         连接类型跟ALL一样,不同的是它只扫描索引树。它通常会比ALL快点,因为索引文件通常比数据文件小。
 
    (11)ALL
        对于前面的表的任意行组合,进行完整的表扫描。如果第一个表没有被标识为const的话就不大好了,在其他情况下通常是非常糟糕的。正常地,可以通过增加索引使得能从表中更快的取得记录以避免ALL。
 
possible_keys
        possible_keys字段是指MySQL在搜索表记录时可能使用哪个索引。如果这个字段的值是NULL,就表示没有索引被用到。这种情况下,就可以检查WHERE子句中哪些字段哪些字段适合增加索引以提高查询的性能。创建一下索引,然后再用explain 检查一下。
 
key
       key字段显示了MySQL实际上要用的索引。当没有任何索引被用到的时候,这个字段的值就是NULL。想要让MySQL强行使用或者忽略在 possible_keys字段中的索引列表,可以在查询语句中使用关键字force index, use index或 ignore index。参考SELECT语法。
 
key_len
        key_len 字段显示了mysql使用索引的长度。当key 字段的值为NULL时,索引的长度就是NULL。注意,key_len的值可以告诉你在联合索引中MySQL会真正使用了哪些索引。
 
ref
        表示使用哪个列或常数与索引一起来查询记录。
 
rows
        显示MySQL在表中进行查询时必须检查的行数。 
 
Extra
        本字段显示了查询中mysql的附加信息。以下是这个字段的几个不同值的解释
 
        distinct
        MySQL当找到当前记录的匹配联合结果的第一条记录之后,就不再搜索其他记录了。 
 
 
        not exists
        MySQL在查询时做一个LEFT JOIN优化时,当它在当前表中找到了和前一条记录符合LEFT JOIN条件后,就不再搜索更多的记录了。下面是一个这种类型的查询例子:
        select * from t1 left join t2 on t1.id=t2.id where t2.id is null;
 
        假使 t2.id 定义为 not null。这种情况下,MySQL将会扫描表 t1并且用 t1.id 的值在 t2 中查找记录。当在 t2中找到一条匹配的记录时,这就意味着 t2.id 肯定不会都是null,就不会再在 t2 中查找相同id值的其他记录了。也可以这么说,对于 t1 中的每个记录,mysql只需要在t2 中做一次查找,而不管在 t2 中实际有多少匹配的记录。
 
 
        range checked for each record (index map: #)
 
        mysql没找到合适的可用的索引。取代的办法是,对于前一个表的每一个行连接,它会做一个检验以决定该使用哪个索引(如果有的话),并且使用这个索引来从表里取得记录。这个过程不会很快,但总比没有任何索引时做表连接来得快。
 
        
        using filesort
        MySQL需要额外的做一遍从已排好的顺序取得记录。排序程序根据连接的类型遍历所有的记录,并且将所有符合where条件的记录的要排序的键和指向记录的指针存储起来。这些键已经排完序了,对应的记录也会按照排好的顺序取出来。详情请看"7.2.9how mysql optimizes order by"。
 
        using index
 
        字段的信息直接从索引树中的信息取得,而不再去扫描实际的记录。这种策略用于查询时的字段是一个独立索引的一部分。
 
 
        using temporary
        mysql需要创建临时表存储结果以完成查询。这种情况通常发生在查询时包含了group by和order by子句,它以不同的方式列出了各个字段。
 
        using where
 
        where子句将用来限制哪些记录匹配了下一个表或者发送给客户端。除非你特别地想要取得或者检查表种的所有记录,否则的话当查询的extra字段值不是using where并且表连接类型是all或index时可能表示有问题。
   
        如果你想要让查询尽可能的快,那么就应该注意extra字段的值为using filesort和using temporary的情况。    
 
其他
 
索引没起作用的情况
 
 
1. 使用LIKE关键字的查询语句
 
        在使用LIKE关键字进行查询的查询语句中,如果匹配字符串的第一个字符为“%”,索引不会起作用。只有“%”不在第一个位置索引才会起作用。
 
2. 使用多列索引的查询语句
 
        MySQL可以为多个字段创建索引。一个索引最多可以包括16个字段。对于多列索引,只有查询条件使用了这些字段中的第一个字段时,索引才会被使用。
 
3. 使用OR关键字的查询语句
 
        查询语句的查询条件中只有OR关键字,且OR前后的两个条件中的列都是索引时,查询中才会使用索引。否则,查询将不使用索引。
 
优化数据库结构
 
 
 
        合理的数据库结构不仅可以使数据库占用更小的磁盘空间,而且能够使查询速度更快。数据库结构的设计,需要考虑数据冗余、查询和更新的速度、字段的数据类型是否合理等多方面的内容。
 
 

1. 将字段很多的表分解成多个表

 
        
        对于字段比较多的表,如果有些字段的使用频率很低,可以将这些字段分离出来形成新表。因为当一个表的数据量很大时,会由于使用频率低的字段的存在而变慢。
 
2. 增加中间表
 
        对于需要经常联合查询的表,可以建立中间表以提高查询效率。通过建立中间表,把需要经常联合查询的数据插入到中间表中,然后将原来的联合查询改为对中间表的查询,以此来提高查询效率。
 
3. 增加冗余字段
 
        设计数据库表时应尽量遵循范式理论的规约,尽可能减少冗余字段,让数据库设计看起来精致、优雅。但是合理加入冗余字段可以提高查询速度。 
 
切分查询
        
        比如我们要删除旧的数据,可能需要一次性删除很多数据会锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。将一个大的DELETE语句切成多个较小的查询可以尽可能小的影响MySQL性能,同时还可以减少MySQL复制的延迟,如下:
        DELETE FROM table WHERE create_date < NOW(); 
        替换为
        rows_affected = 0
        do { 
            rows_affected = do_query(
                "DELETE FROM table WHERE create_date < NOW() LIMIT 10000"    
            )
        } while rows_affected > 0
        一次删除一万行数据一般来说是一个比较高效而且对服务器影响也最小的做法,如果每次暂停一会会更好。
 
分解关联查询
 
        有时候将一个大的查询分解为多个小查询是很有必要的。
        
        很多高性能的应用都会对关联查询进行分解,就是可以对每一个表进行一次单表查询,然后将查询结果在应用程序中进行关联,很多场景下这样会更高效,例如:
        SELECT * FROM tag 
        JOIN tag_post ON tag_id = tag.id
        JOIN post ON tag_post.post_id = post.id
        WHERE tag.tag = 'mysql';
        分解为:
        SELECT * FROM tag WHERE tag = 'mysql';
        SELECT * FROM tag_post WHERE tag_id = 1234;
        SELECT * FROM post WHERE post.id in (123,456,567);
        有很多场景都可以使用:比如当应用能够方便地缓存单个查询的结果的时候、当可以将数据分布到不同MySQL服务器上的时候、当能够使用IN()的方式代替关联查询的时候、当查询中使用同一个数据表的时候。
        
优化LIMIT分页
 
        在分页偏移量很大的时候,如LIMIT 10000,20这样的查询,MySQL需要查询10020条记录然后只返回最后20条,前面10000条记录都被抛弃,这样代价非常高。
 
        优化的最简单的办法就是尽可能地使用索引覆盖扫描,而不是查询所有的列。然后根据需要做一次关联操作再返回所需的列,对于偏移量很大的时候,这样做的效率回提升很大,如下:
        SELECT file_id, description FROM film ORDER BY title LIMIT 50, 5;
        修改为:
        SELECT film.film_id, film.description FROM film 
        INNER JOIN (SELCT film_id FROM film ORDER BY title LIMIT 50, 5) AS lim USING(film_id);
        
        这里“延迟关联”将大大提升查询效率,它让MySQL扫描尽可能少的页面,获取需要访问的记录后在根据关联列回原表查询需要的所有列

慢查询explan详解的更多相关文章

  1. MongoDB各种查询操作详解

    这篇文章主要介绍了MongoDB各种查询操作详解,包括比较查询.关联查询.数组查询等,需要的朋友可以参考下   一.find操作 MongoDB中使用find来进行查询,通过指定find的第一个参数可 ...

  2. hibernate(七) hibernate中查询方式详解

    序言 之前对hibernate中的查询总是搞混淆,不明白里面具体有哪些东西.就是因为缺少总结.在看这篇文章之前,你应该知道的是数据库的一些查询操作,多表查询等,如果不明白,可以先去看一下 MySQL数 ...

  3. 【Solr】索引库查询界面详解

    目录 索引库查询界面详解 回到顶部 索引库查询界面详解 q:主查询条件.完全支持lucene语法.还进行了扩展. fq:过滤查询.是在主查询条件查询结果的基础上进行过滤.例如:product_pric ...

  4. MySQL日志文件之错误日志和慢查询日志详解

    今天天气又开始变得很热了,虽然很热很浮躁,但是不能不学习,我在北京向各位问好.今天给大家分享一点关于数据库日志方面的东西,因为日志不仅讨厌而且还很重要,在开发中时常免不了与它的亲密接触,就在前几天公司 ...

  5. Django框架 之 ORM查询操作详解

    Django框架 之 ORM查询操作详解 浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Py ...

  6. ELK查询命令详解

    目录 ELK查询命令详解 倒排索引 使用ElasticSearch API 实现CRUD 批量获取文档 使用Bulk API 实现批量操作 版本控制 什么是Mapping? 基本查询(Query查询) ...

  7. 【转】MySQL查询缓存详解

    [转]MySQL查询缓存详解 转自:https://www.cnblogs.com/Alight/p/3981999.html 相关文章:http://www.zsythink.net/archive ...

  8. MySQL查询缓存详解(总结)

    MySQL查询缓存详解(总结) 一.总结 一句话总结: mysql查询缓存还是可以用用试一试,但是更推荐分布式,比如redis/memcache之流,将数据库中查询的数据和查询语句以键值对的方式存进分 ...

  9. ELK查询命令详解总结

    目录 ELK查询命令详解 倒排索引 倒排索引原理 分词器介绍及内置分词器 使用ElasticSearch API 实现CRUD 批量获取文档 使用Bulk API 实现批量操作 版本控制 什么是Map ...

随机推荐

  1. 数据库之sqlite

    数据创建数据 CREATE TABLE IF NOT EXISTS ArpAudit (ID INTEGER PRIMARY KEY autoincrement NOT NULL, UserName ...

  2. MySQL中SQL语句常见优化策略

    1.避免全表扫描 对查询进行优化,应尽量避免全表扫描,首先应考虑在where 及order by 涉及的列上建立索引. 2.避免判断null 值 应尽量避免在where 子句中对字段进行null 值判 ...

  3. process exporter 配置项解释

    process exporter在prometheus中用于监控进程,通过process exporter,可从宏观角度监控应用的运行状态(譬如监控redis.mysql的进程资源等) 配置文件样例如 ...

  4. libssh

    1.SSH概念 ssh(secure shell),安全外壳协议,由IETF的网络小组所制定.ssh为建立在应用层基础上的安全协议.SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议. ...

  5. 企业级自动化运维工具应用实战ansible

    公司计划在年底做一次大型市场促销活动,全面冲刺下交易额,为明年的上市做准备.公司要求各业务组对年底大促做准备,运维部要求所有业务容量进行三倍的扩容,并搭建出多套环境可以共开发和测试人员做测试,运维老大 ...

  6. vue 的虚拟 DOM 有什么好处?

    vue 中的虚拟DOM有什么好处?快! 首先了解浏览器显示网页经历的5个过程 1.解析标签,生成元素树(DOM树) 2.解析样式,生成样式树 3.生成元素与样式的关系 4.生成元素的显示坐标 5.显示 ...

  7. linux tcp server bind

    如果不是系统管理员: bind()函数 返回失败

  8. c# json数据解析——将字符串json格式数据转换成对象或实体类

    网络中数据传输经常是xml或者json,现在做的一个项目之前调其他系统接口都是返回的xml格式,刚刚遇到一个返回json格式数据的接口,通过例子由易到难总结一下处理过程,希望能帮到和我一样开始不会的朋 ...

  9. BM(Berlekamp-Massey)算法

    线性递推的题目区域赛里还是挺多的,还是有必要学一下 ~ BM(Berlekamp-Massey)算法 ~ 有一个$n$阶线性递推$f$,想要计算$f(m)$,有一种常用的办法是矩阵快速幂,复杂度是$O ...

  10. TCP IP协议和网络安全

    传输层的两个协议:     可靠传输 TCP 分段传输 建立对话(消耗系统资源) 丢失重传netstat -n     不可靠传输 UDP 一个数据包就能表达完整的意思或屏幕广播   应用层协议(默认 ...