mysql的sql性能优化有两点一个是sql语句的优化,一个是索引的优化,本文主要讲的是索引的优化。首先我们需要了解下
1.Mysql执行顺序,即在执行时sql按照下面的顺序进行执行:
from on join where group by having select distinct union order by
sql的执行顺序对sql的性能优化很有帮助,是很重要的。在建立复合索引的时候需要考虑到这点。
举一个例子:
在tb_student中建立一个复合索引 idx_school_grade:
然后有两个sql 看下解释的结果:
1)在当前索引下,哪一个sql索引利用率高?
第一个sql执行的顺序是先执行了 where后的 school_id 然后执行了 group by 后的 grade_id,顺序是和索引的顺序是一致的,type等级为ref
而第二个sql是先执行了 where后的 grade_id 然后执行了 group by 后的 school_id,顺序是和索引的顺序是不一致的,type等级为index,从解释结果看,第一条的sql索引利用率高于第二条的。(索引type从优到差:System-->const-->eq_ref-->ref-->ref_or_null-->index_merge-->unique_subquery-->index_subquery-->range-->index-->all.)
2)怎么优化
如果业务中用到第二个sql,那么就需要调整索引的顺序和sql执行顺序一致。
2. 通过解释语句分析sql(explain关键字)
通过explain可以知道mysql是如何处理语句,分析出查询或是表结构的性能瓶颈。通过expalin可以得到:
1. 表的读取顺序
2.表的读取操作的操作类型
3.哪些索引可以使用
4. 哪些索引被实际使用
5.表之间的引用
6.每张表有多少行被优化器查询
Id: MySQL QueryOptimizer 选定的执行计划中查询的序列号。表示查询中执行select 子句或操作表的顺序,id 值越大优先级越高,越先被执行。id 相同,执行顺序由上至下。
Select_type:一共有9中类型,只介绍常用的4种:
SIMPLE: 简单的 select 查询,不使用 union 及子查询
PRIMARY: 最外层的 select 查询
UNION: UNION 中的第二个或随后的 select 查询,不 依赖于外部查询的结果集
DERIVED: 用于 from 子句里有子查询的情况。 MySQL 会 递归执行这些子查询, 把结果放在临时表里。
Table:输出行所引用的表
Type: 从有到差的顺序如下:(红色标识的是常见的级别。)
System-->const-->eq_ref-->ref-->ref_or_null-->index_merge-->unique_subquery-->index_subquery-->range-->index-->all.
各自的含义如下:
system: 表仅有一行(=系统表)。这是 const 连接类型的一个特例。
const: const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用 System。
eq_ref: 从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用
ref: 连接不能基于关键字选择单个行,可能查找 到多个符合条件的行。 叫做 ref 是因为索引要 跟某个参考值相比较。这个参考值或者是一个常数,或者是来自一个表里的多表查询的 结果值。
ref_or_null: 如同 ref, 但是 MySQL 必须在初次查找的结果里找出 null 条目,然后进行二次查找。
index_merge: 说明索引合并优化被使用了。
unique_subquery: 在某些 IN 查询中使用此种类型,而不是常规的 ref:valueIN (SELECT primary_key FROM single_table WHERE some_expr)
index_subquery: 在 某 些 IN 查 询 中 使 用 此 种 类 型 , 与unique_subquery 类似,但是查询的是非唯一 性索引
range: 只检索给定范围的行,使用一个索引来选择 行。key列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可 以使用 range。
index: 全表扫描,只是扫描表的时候按照索引次序 进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。
all: 最坏的情况,从头到尾全表扫描。
possible_keys : 指出能在该表中使用哪些索引有助于 查询。如果为空,说明没有可用的索引。
key: 实际从 possible_key 选择使用的索引。 如果为 NULL,则没有使用索引。很少的情况 下,MYSQL 会选择优化不足的索引。这种情 况下,可以在 SELECT语句中使用 USE INDEX (indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制 MYSQL 忽略索引
key_len: 使用的索引的长度。在不损失精确性的情况 下,长度越短越好。
ref: 显示索引的哪一列被使用了
rows: 认为必须检查的用来返回请求数据的行数
extra: 中出现以下 2 项意味着 根本不能使用索引,效率会受到重大影响。应尽可能对此进行优化。
Using filesort: 没有办法利用现有索引进行排序,需要额外排序,建议:根据排序需要,创建相应合适的索引
Using temporary: 需要用临时表存储结果集,通常是因为group by的列列上没有索引。也有可能是因为同
时有group by和order by,但group by和order by的列又不一样Using index : 利用覆盖索引,无需回表即可取得结果数据,这种结果是好的。
其中重要的几个就是 key、type 、rows、extra,其中key为null时,说明没有使用到索引,需要调整索引,type为all的地方,都是需要进行优化的地方.一般需要达到 ref级别,范围查找需要达到 range,extra有Using filesort、Using temporary 的一定需要优化,根据rows可以直观看出优化结果。
3.如果以上优化还是有问题,可以使用show profiles 分析sql 性能(
show profiles; show profile for query [queryId];)
具体请查看:
https://blog.csdn.net/aeolus_pu/article/details/7818498
索引相关知识:
查看表索引:
show index from 【table】
--直接创建索引
CREATE INDEX indexName ON table(column(length))
--修改表结构的方式添加索引
ALTER tableADD INDEX 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`),
INDEX indexName (title(length))
)---主键索引
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
---唯一索引
ALTER TABLE `table_name` ADD UNIQUE (`column` )
---普通索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
全文索引,存储引擎为MYSAM时有效
ALTER TABLE `table_name` ADD FULLTEXT ( `column` )
删除索引:1)ALTER TABLE table_name DROP INDEX index_name
2)DROP INDEX index_name ON table_name;
何时使用聚集索引或非聚集索引?
动作描述 | 使用聚集索引 | 使用非聚集索引 |
列经常被分组排序 | 使用 | 使用 |
返回某范围内的数据 | 使用 | 不使用 |
一个或极少不同值 | 不使用 | 不使用 |
小数目的不同值 | 使用 | 不使用 |
大数目的不同值 | 不使用 | 使用 |
频繁更新的列 | 不使用 | 使用 |
外键列 | 使用 | 使用 |
主键列 | 使用 | 使用 |
频繁修改索引列 | 不使用 | 使用 |
mysql相关配置参数优化:
• sort-buffer-size/join-buffer-size / read-rnd-buffer-size,4~8MB为宜
• optimizer_switch=“index_condition_pushdown=on,mrr=on,mrr_cost
_based=off,batched_key_access=on”
• tmp-table-size = max-heap-table-size,100MB左右为宜
• log-queries-not-using-indexes & log_throttle_queries_not_using_indexes