mysql查缺补漏(二)mysql5.6性能优化(explain执行计划术语,索引,优化查询)

目标

了解什么是优化

掌握优化查询的方法

掌握优化数据库结构的方法

掌握优化mysql服务器的方法

什么是优化

合理安排资源,调整系统参数使得mysql运行更快,更节省资源

优化是多方面的,包括查询、更新、服务器等

原则: 减少系统瓶颈,减少资源占用,增加系统的反应速度

数据库性能参数

使用 show status 语句查看mysql数据库的性能参数

扫描二维码关注公众号,回复: 1376128 查看本文章

* show status like 'value'

常用的参数: slow_queries 慢查询次数   com_(CRUD) 操作的次数  Uptime 上线时间

查询优化

1. explain  

在mysql中可以使用explain查看sql的执行计划,用法: explain select * from tb_item,

explain 查询语句


参数说明:

id:  select 识别码。这是select查询序号,不重要

select_type:表示SELECT语句的类型

1.  SIMPLE 表示简单查询,其中不包含连接查询和子查询

2. PRIMARY 表示主查询 或者是 最外围的查询语句

3. UNION 表示连接查询union 后的查询 ,就像下面的历史表查询

explain select * from ( select * from red_packet union all select * from red_packet_his) m 


4.  DEPENDENT UNION

UNION中的第二个或后面的SELECT语句,取决于外面的查询。

5. UNION RESULT

连接查询的结果

6. SUBQUERY

子查询中的第一个select语句

explain select * from red_packet where send_aip_no =  (
select send_aip_no from red_packet where gain_type = '1'


7、  DEPENDENT SUBQUERY
子查询中的第1个SELECT语句,取决于外面的查询。

8、  DERIVED
SELECT (FROM 子句的子查询)

table :表示查询的表

type:表示表的连接类型(重要)

以下的连接类型的顺序是从最佳到最差

1. system 

表仅有一行,这是const类型的特例,平时不会出现,只是特例

2. const

数据表只有一行匹配到,查询速度很快,常用于主键索引或者唯一索引的查询,可以理解为const的查询是最优

3. eq_ref

mysql手册是这样说的:"对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY"。eq_ref可以用于使用=比较带索引的列。

select * from user_info,order_info where user_id = source_order;

也就是 连接查询中的连接语句中的列,用到了唯一索引或者是主键索引


4. ref

查询条件的索引既不是primary key 也不是 unique, ref 用于 = 或<或>操作符带索引的列

select * from user_info,order_info where user_num = source_order;  比如user_num是索引列,

这个查询的执行计划的type就是ref

5、  ref_or_null
该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

 

上面这五种情况都是很理想的索引使用情况。

6、  index_merge
该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

7、  unique_subquery
该类型替换了下面形式的IN子查询的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr) 
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。

8、  index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)

9、 range
只检索给定范围的行,使用一个索引来选择行

10、index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。

11、ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。(全表扫描,性能最差)

possible_key

表示mysql能使用哪个索引在该表中找到行,如果改列为null,说明没有使用索引,可以对

该列创建索引提高性能。

key

显示mysql实际查询中使用到的索引,如果没有用到,显示为null

可以强制使用索引或忽略索引:

select * from tb_user  ignore index(age) where age<10; ---强制忽略索引

select * from tb_user  use index(age) where age<10; ---强制使用索引

key_len

显示mysql决定使用的键的长度,如果没有用到键,则是null

ref

显示使用哪个列或常数与key一起从表中选择行

rows

mysql执行时,扫描的行数

extra(显示mysql解决查询的详细信息)

该列包含MySQL解决查询的详细信息

  • Distinct:MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
  • Not exists:MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
  • range checked for each record (index map: #):MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
  • Using filesort:MySQL需要额外的一次传递,以找出如何按排序顺序检索行。
  • Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
  • Using temporary:为了解决查询,MySQL需要创建一个临时表来容纳结果。
  • Using where:WHERE 子句用于限制哪一个行匹配下一个表或发送到客户。
  • Using sort_union(...), Using union(...), Using intersect(...):这些函数说明如何为index_merge联接类型合并索引扫描。
  • Using index for group-by:类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。

索引

索引创建
1. --------单列索引-----------
普通索引
create index index_name on 'tablename' ('字段名'(length))
或 alter table tablename add index indexname ('字段名'(length))
index_name 可以省略不写,
如果是char,varchar类型,length可以小于字段的实际长度,如果是BLOB和text类型,必须指定长度
举例: alter table user_info add index ('score');
–直接创建索引
CREATE INDEX index_name ON table(column(length))
–修改表结构的方式添加索引
ALTER TABLE table_name ADD INDEX index_name ON (column(length))
–创建表的时候同时创建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
INDEX index_name (title(length))
)
–删除索引
DROP INDEX index_name ON table


唯一索引
和普通索引类似,但是不同的是唯一索引要求所有的字段的值是唯一的,允许有null值,创建的语法和上面类似
–创建唯一索引
CREATE UNIQUE INDEX indexName ON table(column(length))
–修改表结构
ALTER TABLE table_name ADD UNIQUE indexName ON (column(length))
–创建表的时候直接指定
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
UNIQUE indexName (title(length))
);


主键索引
主键索引的建立规则是int优于varchar,一般在建表的时候创建,最好是业务无关的列,一般设置为int
,而是自增的
全文索引
MySQL从3.23.23版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表;他们可以从CHAR、VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或CREATE INDEX被添加。对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引,
其速度比把资料输入现有FULLTEXT索引的速度更为快。不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。
–创建表的适合添加全文索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
FULLTEXT (content)
);
–修改表结构添加全文索引
ALTER TABLE article ADD FULLTEXT index_content(content)
–直接创建索引
CREATE FULLTEXT INDEX index_content ON article(content)


2. 组合索引

包含多个字段但是只有索引名称,创建格式:
create index indexname on 'tablename'(col1,col2,col3....)
组合索引使用注意:
1. 组合索引遵循'最左前缀原则',比如 key(a,b,c),可以支持a | a,b| a,b,c 3中组合进行查询,但是不支持b,c进行查询,这种情况下,查询时候索引不会采用。
举个例子:
order_no(user_name,user_age,order_no)
where user_name = '' and user_age = '' and order_no ='' 或 user_name = ''或 user_name = '' and user_age = '' 会用到索引,
where user_age = ''   where order_no = '' 不会用到索引
2. 查询中的某个列是范围查询,则右边的所有列都无法使用索引
where user_name = 'zhouy' and user_age like '1%' and order_no ,那么在mysql执行中,只会对
user_name ,user_age 使用索引,而不是对三个列使用索引

索引的优点
1.可以通过建立唯一索引或者主键索引,保证数据库表中每一行数据的唯一性.
2.建立索引可以大大提高检索的数据,以及减少表的检索行数
3.在表连接的连接条件 可以加速表与表直接的相连 
4.在分组和排序字句进行数据检索,可以减少查询时间中 分组 和 排序时所消耗的时间(数据库的记录会重新排序)
5.建立索引,在查询中使用索引 可以提高性能
索引的缺点
1.在创建索引和维护索引 会耗费时间,随着数据量的增加而增加
2.索引文件会占用物理空间,除了数据表需要占用物理空间之外,每一个索引还会占用一定的物理空间
3.当对表的数据进行 INSERT,UPDATE,DELETE 的时候,索引也要动态的维护,这样就会降低数据的维护速度,(建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快)

索引失效的几种情况
1.  like 关键字, %出现在第一个位置'%XXX'索引失效
2. 索引不存储null值, 更准确的说是单列索引不存储null,复合索引不存储全为null的值。索引不能存储null
所以对这列采用is null 条件时候,因为根本上没null值,不能利用到索引,会全表扫描
3. 不适合键值较少的列(重复数据较多的列) 

假如索引列TYPE有5个键值,如果有1万条数据,那么 WHERE TYPE = 1将访问表中的2000个数据块。

再加上访问索引块,一共要访问大于200个的数据块。

如果全表扫描,假设10条数据一个数据块,那么只需访问1000个数据块,既然全表扫描访问的数据块

少一些,肯定就不会利用索引了

4. 如果条件中有or,即使条件的列有索引也不会用到索引 ,只有当or 用到的所有列都有索引,才能使得索引生效
5. 多列索引,只有最左列用到了,索引才会生效,最左前缀原则
6. 如果类的类型是字符串,但是在使用中没有使用引号将数据引起来 ,也不会用到索引
7. 不要在列上进行运算,这样不会用到索引
8.  当前表 union all  历史表 作为临时表 使用索引字段查询,不会用到索引,只能  当前表  where  索引  union all 历史表 where 索引,才能用到索引
select * from (select * from user_info union all select * from user_info_his) m where m.user_name = '';//不会用到索引
改为:
select * from (select * from user_info where user_name = '' union all select * from user_info_his 
where user_name = '' ) m;这样会用到索引

9. mysql认为全表扫描执行更快,也不会用到索引

最后,对于查询的优化,除了使用索引,还可以将数据存储到缓存中(例如存放主键列,在查询表),和将子查询改为连接查询等手段.


数据库表的优化

 创建中间表,如果连接经常使用,可以创建中间表,减少创建临时表的开销

插入数据的优化
影响数据插入的速度主要是索引,唯一性校验,一次插入的数据等。数据插入的优化,不同的存储引擎,优化手段不同
MyISAM
禁用索引
对于非空表,插入记录时,MySQL会根据表的索引对插入的记录建立索引。如果插入大量数据,建立索引会降低插入数据速度。
为了解决这个问题,可以在批量插入数据之前禁用索引,数据插入完成后再开启索引。
禁用索引的语句:
ALTER TABLE table_name DISABLE KEYS
开启索引语句:
ALTER TABLE table_name ENABLE KEYS
对于空表批量插入数据,则不需要进行操作,因为MyISAM引擎的表是在导入数据后才建立索引。
禁用唯一性检查
唯一性校验会降低插入记录的速度,可以在插入记录之前禁用唯一性检查,插入数据完成后再开启。
禁用唯一性检查的语句:SET UNIQUE_CHECKS = 0;
开启唯一性检查的语句:SET UNIQUE_CHECKS = 1;
批量插入数据
插入数据时,可以使用一条INSERT语句插入一条数据,也可以插入多条数据。
第二种方式的插入速度比第一种方式快。
使用LOAD DATA INFILE
当需要批量导入数据时,使用LOAD DATA INFILE语句比INSERT语句插入速度快很多。

InnoDB
禁用唯一性检查
用法和MyISAM一样
禁用外键检查
插入数据之前执行禁止对外键的检查,数据插入完成后再恢复,可以提供插入速度。
禁用:SET foreign_key_checks = 0;
开启:SET foreign_key_checks = 1;
禁止自动提交
插入数据之前执行禁止事务的自动提交,数据插入完成后再恢复,可以提供插入速度。
禁用:SET autocommit = 0;
开启:SET autocommit = 1;


转载自
1. http://www.cnblogs.com/520playboy/p/7795794.html
2. https://www.cnblogs.com/chenshishuo/p/5030029.html
3. https://www.cnblogs.com/binyue/p/4058931.html






 





猜你喜欢

转载自blog.csdn.net/ditto_zhou/article/details/79125934