mysql的优化(explain)
作者:bin一、数据表优化
1.使用optimize table tablename进行优化
使用场景:类似text\blob类型在进行删除操作后会留下很大的“空洞”,之后填入这些“空洞”数据的插入性能会有影响
使用命令,在删除大量数据后进行优化。
optimize table tablename
2.使用合成索引,提高查询性能
应用场景:类似text\blob类型进行精准匹配,又要减少io,使用散列值来查询
使用方式
创建表格,添加hash_value索引
create table t12(id varchar(100), context blob, hash_value varchar(40));
插入一条数据
insert into t12 values(1,repeat(‘beijing’,2),md5(context));
使用hash_value进行查询
select * from t12 where hash_value = md5(repeat(‘beijing 2008’,2));
3.
二、优化sql语句
使用Explain进行分析
explain select name from l_project_profile where id > 1\G;
结果类似
id: 1
sel****ect_type: SIMPLE
table: l_project_profile
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 4
Extra: Using where
1 row in set (0.00 sec)
解释(根据下面的分析,对你的sql进行优化):
table:显示这一行的数据是关于哪张表的
type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和all
possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从where语句中选择一个合适的语句
key: 实际使用的索引。如果为null,则没有使用索引。很少的情况下,mysql会选择优化不足的索引。这种情况下,可以在select语句中使用use index(indexname)来强制使用一个索引或者用ignore index(indexname)来强制mysql忽略索引
key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows:mysql认为必须检查的用来返回请求数据的行数
extra:关于mysql如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是using temporary和using filesort,意思mysql根本不能使用索引,结果是检索会很慢]
type字段解释:
从上至下=由坏到好。
字段解释:
**all**:通俗说的“全表扫描”
如果是在一个查找数据项的sql中出现了all类型,那通常意味着你的sql语句处于一种最原生的状态,有很大的优化空间**index** : 另一种意义上的“全表扫描”
这种连接类型只是另外一种形式的全表扫描,只不过它的扫描顺序是按照索引的顺序。
他比all好事因为,如果使用了order by进行排序,index会比all快**index_merge**:
当查询中使用2个索引时候会用到**range**:有范围的索引扫描
相对于index的全索引扫描,它有范围限制,因此要优于index。关于range比较容易理解,需要记住的是出现了range,则一定是基于索引的。同时除了显而易见的between,and以及>,<外,in和or也是索引范围扫描。**ref**: 查找条件列使用了索引而且不为主键和unique
意思就是虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。**ref_eq**:ref_eq 与 ref相比牛的地方是,它知道这种类型的查找结果集只有一个
那便是使用了主键或者唯一性索引进行查找的情况**const**:
通常情况下,如果将一个主键放置到where后面作为条件查询,mysql优化器就能把这次查询优化转化为一个常量。至于如何转化以及何时转化,这个取决于优化器。
extra字段解释:
**distinct**:
一旦mysql找到了与行相联合匹配的行,就不再搜索了**not exists**:
mysql优化了left join,一旦它找到了匹配left join标准的行,就不再搜索了**range checked for each record(index map:#)**:
没有找到理想的索引,因此对于从前面表中来的每一个行组合,mysql检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一**using filesort(看到这个的时候,查询就需要优化了)**:
mysql需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行**using temporary(看到这个的时候,查询需要优化了)**:
这里,mysql需要创建一个临时表来存储结果,这通常发生在对不同的列集进行order by上,而不是group by上**using index**:
表示直接访问索引就足够获取到所需要的数据,不需要通过索引回表;**Using where** :
表示优化器需要通过索引回表查询数据;**where used**:
使用了where从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型all或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)**system**:
表只有一行:system表。这是const连接类型的特殊情况**const**:
表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为mysql先读这个值然后把它当做常数来对待**eq_ref**:
在连接中,mysql在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用**ref**:
这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好**range**:
这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况 **index**: 这个连接类型对前面的表中的每一个记录联合进行完全扫描(比all更好,因为索引一般小于表数据) **all**: 这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免
优化贴士
Using filesort
filesort是最耗时的
1、优化order by 语句,使用索引进行排序
2、语句中尽量不适用` id!=1、id>1、id<2 `等语句 3:如果排序方式使用的是主键升序,那么就不需要使用order by id 了。 通过更改order by 为索引可以避免这种情况
Using temporary
Using temporary 同样是order by 排序问题
mysql需要借助一个临时表进行排序
内容收集于网络,供大家参考