您的位置:首页 > 数据库 > MariaDB

<<深入理解mariadb和mysql>>之mysql执行计划分析学习记录

2017-02-07 22:21 756 查看
统计信息

只包括记录条数和索引唯一值个数

永久统计信息:

mysql 5.6

show index stats

或查看表innodb_table_stats和innodb_index_stats

create table   engine=innodb stats_persistent={DEFAULT|0|1}

为1表示统计信息保存在上面两个表中,为0表示不保存,用5.5前的管理方式,default时由下面参数来决定.

show global variables like 'innodb_stats_persistent';---由这个参数控制,默认为on,表示

每当遇到下列情形时,会重新收集:

新打开数据表时;

大量修改表的记录时(在数据表的全部记录中执行1/16的update、insert、delete时)

执行analyze tables时

执行show table status或show index from命令时

激活innodb监视器时

innodb_stats_on_metadata设置为on并执行show table status时

建表时,stats_auto_recalc为1表示自动收集  为0表示只能用analyze table收集,default时由参数 innodb_stats_auto_recalc(默认为on)值决定。

innodb_stats_persistent_sample_pages参数默认为20,表示执行analyze table时取20个页面收集,并将结果保存为永久统计信息

innodb_stats_transient_sample_pages 默认为8个,取8个页块,分析结果作为统计信息

mariadb:

使用综合统计信息:

table_stats、index_stats、column_stats

当use_stat_tables 为never时,使用永久统计信息

为preferably时,使用综合统计信息

为complementary,优先使用各引擎的统计信息,信息不足时,才使用综合信息;

当use_stat_tables 为never时,执行analyze table,只收集存储引擎的统计信息,为preferably或complementary时,才会同时收集引擎和综合统计信息。

analyze table用法:

analyze table tb1 persistent for columns (col1,col2) indexes (idx1,idx2);

analyze table tb1 persistent for columns (col1,col2) indexes ();

analyze table tb1 persistent for columns () indexes (idx1,idx2);

analyze table tb1 persistent for columns () indexes ();

analyze table tb1 persistent for all;

直方图:

 高度均衡直方图:先对所有列值 进行排序,再按相同的记录个数将其划分为几个组,然后取各组的最后一个值(排序后的最大值)保存到直方图

histogram_size默认为0,表示不使用直方图

使用直方图:

set histogram_size=20;

set use_stat_tables='preferably';

set histogram_type='double_prec_hb';

优化器连接优化参数:

optimizer_prune_level  默认为1,表示用Greedy检索算法,为0表示用exhaustive检索算法(n!种执行计划选择最优的一个)。

optimizer_search_depth=64  对greedy算法有用

查看具体时间使用:

set profiling=1

select ...

show profiles;

show profile cpu for query 1;

set session  optimizer_search_depth=10   ---当表比较多时,可以降低这个值 。

select_type列:

simple:需要union或子查询是的select

primary:需要union或含有子查询执行计划中,位于最外层的查询

union:由union组合成的查询中,除第一个外,第二个以后的所有查询都为union,由于有多个查询用union或union all进行联合,并创建临时表进行使用,所以union的第一个查询为DERIVED(

派生),若是在from后的第一个为派生

如:

select * from a where ...

uinon

select * from b where ...

dependent union和dependent subquery:当union作为子查询时,其中第二个union的select_type就是DEPENDENT UNION。

第一个子查询的select_type则是DEPENDENT SUBQUERY。当含 有DEPENDENT关键字的子查询时,外部查询先执行,子查询后执行,一般这种性能比较低.

dependent 表示union或union all受单位查询外部影响 ,若子查询需要使用外部查询中定义的列,则为dependent subquery.

如:

select * from a where a.id in (

select b.id from B where ....

union

select c.id from C where ....)

union result:包含union结果的数据表(临时表),因为不是一个查询,所以没有id值 。

subquery:除指from子句以外的子查询

derived:需要创建临时表,from子句的子查询

uncacheable subquery:

  subquery:不受外层查询影响 ,只执行一次,将结果缓存,后面每次使用缓存中的结果。

  dependent subquery:依赖外部查询列值为单位进行缓存

  下面三种无法使用缓存:

  a.子查询含有用户变更时,b.子查询含 用OT-DETERMINISTIC属性的存储列程时

  c.子查询使用每次调用有不同结果值的函数时(如uuid()或rand())

materialized:

用于优化from子句或in查询中的子查询,子查询内容具体化为临时表,与derived类似.

table列:

<derived N> <union M,N>,表示临时表,数字表示执行计划中的id

materialized执行计划中table列会出现<subquery N>,表示将子查询结果具体化为临时表.

from子句的子查询必需要有别名。

type列:就是访问方式

1.system --访问仅有1条记录或没有记录的空表时,只适应myisam或memory引擎表中

2.const --通过主键或唯一键等值条件访问数据,有且只返回一行记录,相当于唯一索引扫描,常量化处理

3.eq_ref --多表连接中,第一次读取的表列值,作为读取第二张表的主键或唯一键等值检索条件,第二张表只返回一条记录

4.ref --使用等值条件检索,不保证返回一条记录。

执行计划中ref列中的const表示条件中的值是常量

5.fulltext---match ..against...条件查询

6.ref_or_null---是ref和is null的组合

7.unique_subquery --in查询中,in后面不返回重复值,所以不需要删除重复值

8.index_subquery --in查询或in(常数列表),in后面可能返回重复值 ,使用索引删除重复值

9.range ---范围扫描

10.index_merge ---使用两个以上的索引获得结果后,再将其进行合并

11.index --全索引扫描,排序时加上limit,获得较好的性能

12.all ---全表扫描

key_len列:

1.可以根据执行计划的ken_len来判断复合索引中字段是否有使用,计算规则如下:

 当索引字段为定长数据类型,比如char,int,datetime,需要有是否为空的标记,这个标记需要占用1个字节;对于变长数据类型,比如:varchar,除了是否为空的标记外,还需要有长度

信息,需要占用2个字节;同时还需要考虑表所使用的字符集,不同的字符集,gbk编码的为一个字符2个字节,utf8编码的一个字符3个字节,latin为1字节

2.单表排序时,order by后面字段顺序需要与复合索引中字段顺序一致时,才能用索引,符合索引的最左原则,且select后面字段需为索引字段的部分或全部。

3.order by 或group by 的字段不参与key_len长度计算。

integer类型:4字节

date类型:3字节  若同时定义了nullable列,则需加1为4

ref列:提供了哪种值作为参考条件,常数值显示为const,若为其它表的列值,则显示数据表名或列名

当为func时,表示经过排序或运算变换

rows:指处理查询时要从磁盘读取与检查多少条记录,不是返回记录数,估计值。

extra列:

 1.const row not found --虽然使用const访问方式读取了数据表,但若实际数据表中没有1条符合条件的记录,建议先向表中存储适当的测试数据,再查看执行计划.



2.distinct--表示去重

3.full scan on null key ---出现在col1 in (select col2 from ...)时,当col1为null时,就会发生全表扫描,建议在定义col1为非空或sql中加入where col1 is not null来避免。一

4.impossible having

 不存在满足having子句条件的记录时,会显示impossible having,出现这个,表示sql编写错误

5.impossible where --同impissible having一样

6.impossible where noticed after reading const tables --- 读数据表后,发现记录不存在

7.no matching min/max row ---查询中有mix和max,但没有符合条件的记录,返回空值 。

8.no matching row in const table ---以const方式访问连接中的数据表时,不存在符合条件的记录.

9.no tables used --不带有from子句的查询或from dual查询的计划中

10.not exists ---使用外部连接进行反连接的查询中的extra会出现not exists

11.range checked for each record(index map:n) ---在连接两个表的查询中,连接条件不是常量,而两个变量或两个字段,如where e2.emp_no>e1.emp_no

  index map:n中的n为16进制,换成二进制,对应位置为1表示备选索引在表中出现顺序.

12.scanned N database ---查看information_schema库的信息时,才会有

13. select tables optimizer away ---select只使用min()或max(),或者用group by访问min或max时,若无法使用合适的索引,就会按升序或降序只读取一个索引。

14.unique row not found--两个表的唯一键(含主键)执行外部连接查询,若外连接表中不存在一样的记录。

15.using filesort ---当没有索引时,就会出现,先读取数到排序缓存区,排序后返回到客户端

16 using index ---只读取索引内容,覆盖索引

17 using index for group-by --先用索引排序,然后再分组

18 using join buffer(block nested loop)、using join buffer(batched key access)

 读取驱动的表的记录放到临时的内存空间(join_buffer_size)

19 using sort_union、using union、using intersect、using sort_intersect

  都是index_merge操作的四种方式

  using sort_union和using union是or操作,后两个是and操作

  有sort的表示先排序操作

20 using temporary

  临时表使用

21 use where ---表示mysql层进行数据加工和过滤处理

22 using where with pushed condition ---适合NDB引擎,条件下推

23 deleting all rows ---删除所有记录

24 FirstMatch(tbl_name)---是将in子查询转换成exists的优化方式,tbl_name为外部表,表示从外部表读一条记录,再从子查询检索记录,直到匹配到记录为止

若子查询中一次就可找到符合条件的记录,则执行代价非常小,若不存在任何符合条件的记录,则执行代价变得非常高。

mairadb 10采用是materialized优化

25 loosescan(m..n)--用于in子查询中可能产生重复记录时

先使用using index scan访问方法读取子查询内容,然后删除重复记录时,要使用lossescan优化方法,不需要使用临时表。

使用方法:

  set optimizer_switch=default;

  set optimizer_switch='firstmatch=off';

  set optimizer_switch='materialization=off';

26 materialize、scan

 mysql 5.6和mariadb 10前几个版本的extra会显示,后期版本没有显示,但会在select_type中显示materialized,显示scan,表示不为具体化内容创建索引,走全表扫描,不显示scan

表示为具体化的临时表建索引,并将其用作lookup

27 start temporary、end temporary

优化子查询

先访问子查询,然后将与外部查询数据表连接后的结果存储到临时表,之后再删除重复记录。子查询表在执行计划中的extra显示start temporay,外部表显示end temporary。

28 using index condition

索引条件下推

29 rowid-ordered scan、key-ordered scan

MRR(多范围读)---先通过索引读取符合where条件的记录,然按主键排序,再从实际数据文件中读取其余数据列,减少随机IO

Mysql 5.6显示using MRR

mairaDB显示rowid-ordered scan和key-ordered scan

其中mysql 5.6的using MRR只相当于rowid-ordered scan

key-ordered scan是用于主键与连接的查询中,多表连接中,其中有一个表的连接字段为主键,对符合条件的记录按连接字段进行排序,然后再连接。

开启方法:

set optimizer_switch='mrr=on';

set optimizer_switch='mrr_sort_keys=on';

set join_cache_level=8;

4.3.11 explain extended(filtered列)

 filtered列表示过滤后剩下的记录数占读取总记录数的百分比,估计值

4.3.12 explain extended(附加优化器信息)

show warnings 查看优化器分析重组后的查询语句

4.3.13 explain partitions,分增加partitions列,显示查询使用的分区目录

4.4优化器提示

4.4.1 提示使用方法

create /*!32302 temporary */  table ...

当版本大于等于3.23.02时,执行create tmporary table,低于此版本,执行create table..

主版本取第一位数,次版本号取两位,修订版本号取两位。

4.4.2 straight_join

select straight_join ...



select /*!straight_join*/ ....

强制指定from后表按顺序连接。

或直接将inner join 改成straight_join

适用于普通表与临时表之间、普通表与普通表之间、临时表与临时表之间,这里临时表是批派生表或内嵌视图

4.4.3 use index/force index/ignore index

在表名或表别名后加use index()

4.4.4

sql_cache/sql_no_cache

与query_cache_type设置有关,

无提示时,只有等于1(on)时才缓存;

sql_cache时,等于1(on)或2(demand)时才缓存

sql_no_cache时,都不缓存

若能选择性的工作,当设置为2,再加上sql_cache提示时即可,

4.4.5 sql_calc_found_rows

当加了这个提示时,mairadb查找到limit指定条数的记录之后,还会继续检索,最终还是会返回limit指定记录数.

用found_rows()返回符合条件的记录数。

4.5 分析执行计划需要注意的事项

4.5.1 select_type

derived,注意临时表是否在磁盘中

dependent subquery --去除子查询对外部查询的依赖。

4.5.2 type列

all和index

4.5.3 key列

为空时,注意增加索引

4.5.4 rows列

rows列不受limit限制

若值比实际的记录数多时,检查索引使用情况

4.5.5 extra列

查询条件执行计划不佳:

range checked for each record(indedx map:N)

using filesort

using join buffer

using temporary

using where

 

 

 

 

 

 

 

 

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: