Mysql优化-重中之重

数据库查询时的步骤如下图,循序渐进.
客户端 ->查询缓存->解析器->解析树->预处理器—>查询执行计划->查询执行引擎->存储引擎->数据->返回结果

我先向大家展示我的ads数据库表结构,结合这些信息完成优化。
desc ads;
+------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+-------+
| ads_id | char(36) | NO | PRI | NULL | |
| ads_media_type | tinyint(4) | YES | | NULL | |
| ads_type | tinyint(4) | YES | | NULL | |
| ads_business | varchar(255) | YES | | NULL | |
| ads_status | tinyint(4) | YES | | NULL | |
| ads_path | varchar(255) | YES | | NULL | |
| ads_relate_type | tinyint(4) | YES | | NULL | |
| ads_keywords | varchar(255) | YES | | NULL | |
| ads_external_url | varchar(255) | YES | | NULL | |
| ads_desc | varchar(255) | YES | | NULL | |
| ads_add_time | datetime | YES | | NULL | |
| ads_relate_id | varchar(36) | YES | | NULL | |
| su_id | int(11) | YES | | NULL | |
+------------------+--------------+------+-----+---------+-------+

一,通过为字段添加索引的方式增加查询效率。
说到mysql优化,我一定会想到这张表的内容,呵呵,优化从这里开始。
表 1
+------+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | ads | ALL | NULL | NULL | NULL | NULL | 5 | |
+------+-------------+-------+------+---------------+------+---------+------+---

这张表是怎么来的呢? 是我们在查询的时候,前面加了一个mysql的关键字explain,就能看到这表1了,比如: explain select * from ads ;

我还是先给你们卖一个关子,为了验证可比性,我小小的优化了ads表。
首先我给ads表的ads_type 添加了一个索引:alter table ads add index ads_typo_index on ads_type;
然后根据ads_type查询了这张表,并查询了执行过程,得到下面的表2
explain select*from ads where ads_type=2;
表 2
+------+-------------+-------+------+----------------+----------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+----------------+----------------+---------+-------+------+-------+
| 1 | SIMPLE | ads | ref | ads_typo_index | ads_typo_index | 2 | const | 2 | |
+------+-------------+-------+------+----------------+----------------+---------+-------+------+-------+
说到这里,也许道家看到了这两张表的区别。我开始解释这两张表中的字段对照上面两张表进行一一解释
table #你查询的哪张表。表1和表2都是ads

type #这列很重要,显示了连接使用了哪种类别,有无使用索引,反映语句的质量。

possible_keys #列指出MySQL能使用哪个索引在该表中找到行

key #显示MySQL实际使用的键(索引)。如果没有选择索引,键是NULL。表1没有使用索引,表2使用了ads_typo_index这个我添加的索引.

key_len #显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好

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

rows #显示MySQL认为它执行查询时必须检查的行数。表1的意思是查询了5次才查询到想要的结果,表2的意思是 查询了2次就查询到了结果.

extra #包含MySQL解决查询的详细信息。

其中:Explain的type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL(优-->差) 一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题;可以看出表2的type是ref,而表1的type还是all,显然我添加索引后,按照索引字段去查询的效果比没有添加索引的时候效率高了很多很多,都提高了很高的一个级别。

呵呵,我这些应该给你们讲讲字段id和select_type
id #就是你执行sql语句,这个sql语句在整条sql语句的级别,因为sql语句的查询都是从里面向外面一个个查询的,比如 explain select * from (select * from ( select * from t3 where id=3952602) a) b ,很显然这条SQL是从里向外的执行,就是从id=3 向上执行.

select_type#就容易理解一点了,就是你选择的select类型,分为一下几种。
SIMPLE,就是最简单的查询,比如select *from ads,既没有关联到其他表的查询,也没有子查询.
SUBQUERY,子查询
DERIVED ,派生表的子查询,其实我也不是很懂,呵呵,还有几种,我也不是很理解,就不提及了,怕误人子弟。还有PRIMARY,UNION等等。

总结:虽然添加索引可以增加查询效率,但是例外一个问题出现了,我们来看insert操作,和update操作。
INSERT语句的速度
插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例:
连接:(3)
发送查询给服务器:(2)
分析查询:(2)
插入记录:(1x记录大小)
插入索引:(1x索引)
关闭:(1)
UPDATE语句的速度
更新查询的优化同SELECT查询一样,需要额外的写开销。写速度依赖于更新的数据大小和更新的索引的数量。没有更改的索引不被更新。
因此,不能无谓地为表的所有字段添加索引,因为为所有字段添加索引之后,增加insert和修改update操作的时候就会影响效率,所有要选择一个折中的办法。

技巧:字段最好是经常查询的字段,或者两张表的关联字段建立索引。


二,优化数据库表提高效率
1, 设计数据库表的时候最好是定长表,什么是定长表呢,就是表中所有的字段的长度都是一定的,比如char,int,等等,varchar,text等就不是定长的,所以在设计表的时候最好把字段设计为定长,少用varchar,text等数据类型的字段。



三,优化查询select语句提高查询效率,->表示修改为
1, 去除不必要的括号:((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
2, 常量重叠: (a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
3, 有索引的字段放在离where 条件最近的地方,也就是离where关键字越近越好。
4,合并索引
5,灵活使用查询缓存,在mysql中如果一个查询条件不怎么变化的话,会在mysql的缓存区查找,而不会直接访问mysql服务器,在mysql中curdate(),now(),order by rand(),因为这些词都是可变的,所有最好不要用这些now(),curdate()order by rand(),很消耗时间.
6,需要什么查什么,最好不要用select * from ads; ,你可以这样使用,select ads_type from ads;
7,明知道只能查询出一条记录,也要使用limit 1
8,join两张表的时候,left join on a.字段=b.字段,两张表的关联字段统一,并建立索引。
9,如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。ENUM 其保存的是 TINYINT

今天就先说到这里,后面还会有补充。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值