SHOW STATUS;SHOW WARNINGS;SHOW ERRORS;SHOW FULL PROCESSLIST;
kill id值SHOW STATUS LIKE 'max_used_connections';SHOW VARIABLES;show variables like 'slow%';
set global slow_query_log='ON' show variables like 'long%';
set long_query_time=1;SHOW STATUS LIKE '%slow_queries%';SHOW STATUS LIKE '%Com_select%';SHOW STATUS LIKE '%Com_insert%';SHOW STATUS LIKE '%Com_update%';SHOW STATUS LIKE '%Com_delete%';SHOW STATUS LIKE '%Com_rollback%';SHOW STATUS LIKE 'uptime';SHOW STATUS LIKE 'qcache%';flush query cache; 对缓存中的碎片进行整理,从而得到一个空闲块。SHOW OPEN TABLES WHERE In_use > 0;SHOW ENGINE INNODB STATUS;SHOW STATUS LIKE 'innodb_row_lock_%';
select * from my_table procedure analyse();select * from information_schema.INNODB_TRX;select * from information_schema.INNODB_LOCKS;select * from information_schema.INNODB_LOCK_WAITS;SHOW VARIABLES LIKE 'optimizer_trace';
SET optimizer_trace="enabled=on";SET optimizer_trace="enabled=off";SELECT * FROM information_schema.OPTIMIZER_TRACE;我们所说的基于成本的优化主要集中在optimize阶段,对于单表查询来说,我们主要关注optimize阶段的"rows_estimation"这个过程,这个过程深入分析了对单表查询的各种执行方案的成本;
对于多表连接查询来说,我们更多需要关注"considered_execution_plans"这个过程,这个过程里会写明各种不同的连接方式所对应的成本。
反正优化器最终会选择成本最低的那种方案来作为最终的执行计划,也就是我们使用EXPLAIN语句所展现出的那种方案。
如果有小伙伴对使用EXPLAIN语句展示出的对某个查询的执行计划很不理解,大家可以尝试使用optimizer trace功能来详细了解每一种执行方案对应的成本,相信这个功能能让大家更深入的了解MySQL查询优化器。
EXPLAIN SELECT * FROM sys_user;,效果如下:id|select_type|table |partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|
--|-----------|--------|----------|----|-------------|---|-------|---|----|--------|-----|
1|SIMPLE |sys_user| |ALL | | | | | 2| 100| |
id:在一个大的查询语句中每个 SELECT 关键字都对应一个唯一的idselect_type:SELECT 关键字对应的那个查询的类型table:表名partitions:匹配的分区信息type:针对单表的访问方法possible_keys:可能用到的索引key:实际上使用的索引key_len:实际使用到的索引长度ref:当使用索引列等值查询时,与索引列进行等值匹配的对象信息rows:预估的需要读取的记录条数filtered:某个表经过搜索条件过滤后剩余记录条数的百分比Extra:一些额外的信息SIMPLE:表示简单查询,其中不包括 UNION 查询和子查询PRIMARY:对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARYUNION:对于包含UNION或者UNION ALL的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询以外,其余的小查询的select_type值就是UNIONUNION RESULT:MySQL选择使用临时表来完成UNION查询的去重工作,针对该临时表的查询的select_type就是UNION RESULTSUBQUERY:如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是不相关子查询,并且查询优化器决定采用将该子查询物化的方案来执行该子查询时,该子查询的第一个SELECT关键字代表的那个查询的select_type就是SUBQUERYDEPENDENT SUBQUERY:如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是相关子查询,则该子查询的第一个SELECT关键字代表的那个查询的select_type就是DEPENDENT SUBQUERYDEPENDENT UNION:在包含UNION或者UNION ALL的大查询中,如果各个小查询都依赖于外层查询的话,那除了最左边的那个小查询之外,其余的小查询的select_type的值就是DEPENDENT UNIONDERIVED:对于采用物化的方式执行的包含派生表的查询,该派生表对应的子查询的select_type就是DERIVEDMATERIALIZED:当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询时,该子查询对应的select_type属性就是MATERIALIZEDsystem:当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是system,平时不会出现,这个也可以忽略不计。const:当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是const,常用于 PRIMARY KEY 或者 UNIQUE 索引的查询,可理解为 const 是最优化的。eq_ref:在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较),则对该被驱动表的访问方法就是eq_refref:当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是ref。ref 可用于 = 或 < 或 > 操作符的带索引的列。ref_or_null:当对普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值时,那么对该表的访问方法就可能是ref_or_nullindex_merge:该联接类型表示使用了索引合并优化方法。在这种情况下,key 列包含了使用的索引的清单,key_len 包含了使用的索引的最长的关键元素。unique_subquery:类似于两表连接中被驱动表的eq_ref访问方法,unique_subquery是针对在一些包含IN子查询的查询语句中,如果查询优化器决定将IN子查询转换为EXISTS子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的type列的值就是unique_subqueryindex_subquery:index_subquery与unique_subquery类似,只不过访问子查询中的表时使用的是普通的索引range:只检索给定范围的行, 使用一个索引来选择行。index:该联接类型与 ALL 相同, 除了只有索引树被扫描。这通常比 ALL 快, 因为索引文件通常比数据文件小。
ALL:对于每个来自于先前的表的行组合, 进行完整的表扫描。(性能最差)possible_keys,指出 MySQL 能使用哪个索引在该表中找到行。如果该列为 NULL,说明没有使用索引,可以对该列创建索引来提供性能。(这个属性重要)
key,显示 MySQL 实际决定使用的键 (索引)。如果没有选择索引, 键是 NULL。(这个属性重要)
key_len,表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度。如果键是可以为 NULL, 则长度多 1。ref,显示使用哪个列或常数与 key 一起从表中选择行。rows,显示 MySQL 认为它执行查询时必须检查的行数。(这个属性重要)Extra,该列包含 MySQL 解决查询的详细信息:
Distinct MySQL 发现第 1 个匹配行后, 停止为当前的行组合搜索更多的行。Not exists 当我们使用左(外)连接时,如果WHERE子句中包含要求被驱动表的某个列等于NULL值的搜索条件,而且那个列又是不允许存储NULL值的,那么在该表的执行计划的Extra列就会提示Not exists额外信息range checked for each record (index map: #) MySQL 没有发现好的可以使用的索引, 但发现如果来自前面的表的列值已知, 可能部分索引可以使用。Using filesort 有一些情况下对结果集中的记录进行排序是可以使用到索引的
Using temporary 在许多查询的执行过程中,MySQL可能会借助临时表来完成一些功能,比如去重、排序之类的,比如我们在执行许多包含DISTINCT、GROUP BY、UNION等子句的查询过程中,如果不能有效利用索引来完成查询,MySQL很有可能寻求通过建立内部的临时表来执行查询。如果查询中使用到了内部的临时表,在执行计划的Extra列将会显示Using temporary提示
Using join buffer (Block Nested Loop) 在连接查询执行过程过,当被驱动表不能有效的利用索引加快访问速度,MySQL一般会为其分配一块名叫join buffer的内存块来加快查询速度,也就是我们所讲的基于块的嵌套循环算法Using where
Using sort_union(...), Using union(...), Using intersect(...) 如果执行计划的Extra列出现了Using intersect(…)提示,说明准备使用Intersect索引合并的方式执行查询,括号中的…表示需要进行索引合并的索引名称;如果出现了Using union(…)提示,说明准备使用Union索引合并的方式执行查询;出现了Using sort_union(…)提示,说明准备使用Sort-Union索引合并的方式执行查询。Using index condition 有些搜索条件中虽然出现了索引列,但却不能使用到索引Using index 当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用索引覆盖的情况下,在Extra列将会提示该额外信息Using index for group-by 类似于访问表的 Using index 方式,Using index for group-by 表示 MySQL 发现了一个索引, 可以用来查 询 GROUP BY 或 DISTINCT 查询的所有列, 而不要额外搜索硬盘访问实际的表。select xxx,xxx from test_table where id < '上页id分界值' order by id desc limit 20;ALTER TABLE table_name DISABLE KEYS;ALTER TABLE table_name ENABLE KEYS;SET UNIQUE_CHECKS = 0;SET UNIQUE_CHECKS = 1;SET foreign_key_checks = 0;SET foreign_key_checks = 1;SET autocommit = 0;SET autocommit = 1;SET foreign_key_checks = 0;SET foreign_key_checks = 1;InnoDB支持事务;InnoDB 采用了行级锁。也就是你需要修改哪行,就可以只锁定哪行。 在 Mysql 中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。 InnoDB 行锁是通过给索引项加锁实现的,如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。
数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。
排他锁:对某一资源加排他锁,自身可以进行增删改查,其他人无法进行任何操作。语法为: select * from table for update;
共享锁:对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源(也可以再继续加共享锁,即 共享锁可多个共存),但无法修改。 要想修改就必须等所有共享锁都释放完之后。语法为: select * from table lock in share mode;