慢查询:
- 确认应用程序是否检索了大量超过需求的数据,访问了太多的行或者列
- 是否分析了超过需求的行或者列
EXPLAIN type 字段解释
参与连接运算的表是内表
CONST where 条件筛选至多有一条匹配时
EQ_REF 基于索引做扫描、连接字段为唯一索引或主键索引、索引值不为Null、操作符为 =
使得对外表的一条元组,内表只有唯一一条元组与之对应。
REF 基于单表或*强调内容*连接。基于索引做扫描、连接字段非唯一索引或主键索引、连接字段不为Null、操作符为 =
使得对外表的一条元组,内表可有若干条元组与之对应。
REF_OR_NULL 类似REF,只是搜索条件包括:连接字段的值可以为NULL的情况,比如 where col = 2 or col is null
RANGE 范围扫描,基于索引做范围扫描,为诸如BETWEEN,IN,>=,LIKE类操作提供支持
INDEX_SCAN 索引做扫描,是基于索引在索引的叶子节点上找满足条件的数据(不需要访问数据文件)
ALL 全部数据
UNIQUE_SUBQUERY 在子查询中,基于唯一索引进行扫描,类似于EQ_REF
FT FULL TEXT,全文检索
INDEX_SUBQUERY 在子查询中,基于除唯一索引之外的索引进行扫描
INDEX_MERGE 多重范围扫描
index_merge 该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。
ALL
Extra
Distinct Mysql 发现第一个匹配停止匹配
Range checked for each record
Not exists 没有找到合适的索引
using filesort “Mysql需要额外的一次传递,以找出如何按排序顺序检索行,通过根据联接类型浏览所有行并为所有匹配where子句的行保存排序关键字和行的指针来完成排序,然后关键字被排序,并按排序顺序检索行。”
eg: SELECT id FROM test WHERE room=100 ORDER BY id; (room 有索引,id没有索引,使用索引先查出room =1000 的数据,然后再次使用排序来实现结果筛选)
using temporaty; 使用了临时表(典型的连表时使用了group by / order by)
using where 表示优化器需要通过索引回表查询数据;
切分查询:
roes_affect = 0;
do{
roes_affect = do_query(‘DELETE FROM message WHERE created < DATE_SUB (NOW(), INTERVAL 3 MOUNTH) LIMIT 10000’)
} while roes_affect >0 ;
分解关联查询
将多个join拆分成单独的 select
- 可以充分利用mysql_query();
- 执行单个查询,可减少锁竞争
- 使用了哈希关联而不是mysql的嵌套循环关联*
查询流程:
sql -> 查询缓存 -> SQL解析器 -> 预处理器 -> 优化器生成执行计划 -> 调用存储引擎API -> 数据
MYSQL 客户端和服务器之间的通信协议是半双工。
同一时刻,要么是服务器想客户端发送数据,要么客户端向服务器发送数据,不能同时进行。
max_allow_packet
mysql_query VS mysql_unbuffered_query() PHP指定,是否使用内存缓存首先将获取到的数据放到内存中,然后再执行循环操作。
MYSQL 状态查询 SHOW FULL PROCESSLIST
Locked 在mysql 服务层,该线程正在等待表锁. Innodb的行锁不会体现在线程状态中。
Analyzing and statistics 线程正在收集存储引擎的统计信息,并生产查询的执行计划。
Copying to tmp table [on disk] 线程在执行查询计划,并将结果复制到一个临时表中。 一般在做group,文件排序,或者union操做。