浅谈MySQL数据库优化
2007-11-11 13:22:01 来源:WEB开发网核心提示: 3 SELECT优化 3.1 MySQL(和PHP搭配之最佳组合)数据库的SQL执行计划解释器 EXPLAIN tbl_name 或者如下: EXPLAIN [EXTENDED] SELECT select_options EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS
3 SELECT优化
3.1 MySQL(和PHP搭配之最佳组合)数据库的SQL执行计划解释器
EXPLAIN tbl_name
或者如下:
EXPLAIN [EXTENDED] SELECT select_options
EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name的一个同义词。
MySQL(和PHP搭配之最佳组合)> explain a;+-------+---------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+---------+------+-----+---------+-------+| id | int(11) | YES | UNI | NULL | |+-------+---------+------+-----+---------+-------+1 row in set (0.02 sec)MySQL(和PHP搭配之最佳组合)> explain t;+-------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| id | int(11) | NO | PRI | 0 | || MC | varchar(60) | YES | | NULL | |+-------+-------------+------+-----+---------+-------+2 rows in set (0.00 sec)MySQL(和PHP搭配之最佳组合)> select * from t;+-------+------+| id | MC |+-------+------+| 1 | MC || 2 | NULL || 3 | NULL || 4 | NULL || 5 | NULL || 6 | NULL || 7 | NULL || 8 | NULL || 9 | NULL || 10000 | MC |+-------+------+10 rows in set (0.00 sec)MySQL(和PHP搭配之最佳组合)> select * from a;+------+| id |+------+| NULL || 1 || 2 |+------+3 rows in set (0.00 sec)MySQL(和PHP搭配之最佳组合)> explain select * from A where id in (select id from T)\G*************************** 1. row *************************** id: 1 select_type: Prima(最完善的虚拟主机管理系统)RY table: A type: indexpossible_keys: NULL key: idx_a key_len: 5 ref: NULL rows: 3 Extra: Using where; Using index*************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: T type: unique_subquerypossible_keys: Prima(最完善的虚拟主机管理系统)RY key: Prima(最完善的虚拟主机管理系统)RY key_len: 4 ref: func rows: 1 Extra: Using index2 rows in set (0.02 sec)unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:
MySQL(和PHP搭配之最佳组合)> explain select * from test where id in (select id from a)\G*************************** 1. row *************************** id: 1 select_type: Prima(最完善的虚拟主机管理系统)RY table: test type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1534755 Extra: Using where*************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: a type: index_subquerypossible_keys: idx_a key: idx_a key_len: 5 ref: func rows: 1 Extra: Using index2 rows in set (0.00 sec)
range
索引范围扫描,只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range:
MySQL(和PHP搭配之最佳组合)> explain select * from t where id=1 or id=10000 or id=3\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t type: rangepossible_keys: Prima(最完善的虚拟主机管理系统)RY key: Prima(最完善的虚拟主机管理系统)RY key_len: 4 ref: NULL rows: 3 Extra: Using where1 row in set (0.00 sec)MySQL(和PHP搭配之最佳组合)> explain select * from t where id<=3\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t type: rangepossible_keys: Prima(最完善的虚拟主机管理系统)RY key: Prima(最完善的虚拟主机管理系统)RY key_len: 4 ref: NULL rows: 4 Extra: Using where1 row in set (0.00 sec)ERROR:No query specified
index
索引全扫描,该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。当查询只使用作为单索引一部分的列时,MySQL(和PHP搭配之最佳组合)可以使用该联接类型。
MySQL(和PHP搭配之最佳组合)> explain select * from t\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t type: indexpossible_keys: NULL key: idx_t_mc key_len: 63 ref: NULL rows: 10 Extra: Using index1 row in set (0.00 sec)ERROR:No query specified
ALL
全表扫描,对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记cnst的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。
MySQL(和PHP搭配之最佳组合)> explain select * from test\G;*************************** 1. row *************************** id: 1 select_type: SIMPLE table: test type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1534755 Extra:1 row in set (0.06 sec)ERROR:No query specifiedpssible_keys
pssible_keys列指出MySQL(和PHP搭配之最佳组合)能使用哪个索引在该表中找到行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在pssible_keys中的某些键实际上不能按生成的表次序使用。如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询。
为了看清一张表有什么索引,使用SHOW INDEX FROM tbl_name。
MySQL(和PHP搭配之最佳组合)> show index from t;+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+| t | 0 | Prima(最完善的虚拟主机管理系统)RY | 1 | id | A | 2 | NULL | NULL | | BTREE | || t | 1 | idx_t_mc | 1 | MC | A | 2 | NULL | NULL | YES | BTREE | |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+2 rows in set (0.08 sec)key
key列显示MySQL(和PHP搭配之最佳组合)实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL(和PHP搭配之最佳组合)使用或忽视pssible_keys列中的索引,在查询中使用FRCE INDEX、USE INDEX或者IGNRE INDEX。对于MyISAM和BDB表,运行ANALYZE TABLE可以帮助优化器选择更好的索引。对于MyISAM表,可以使用myisamchk --analyze。
MySQL(和PHP搭配之最佳组合)> explain select * from t where id=1 or mc='1'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t type: indexpossible_keys: Prima(最完善的虚拟主机管理系统)RY,idx_t_mc key: idx_t_mc key_len: 63 ref: NULL rows: 10 Extra: Using where; Using index1 row in set (0.00 sec)MySQL(和PHP搭配之最佳组合)> explain select * from t ignore index(idx_t_mc) where id=1 or mc='1'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t type: ALLpossible_keys: Prima(最完善的虚拟主机管理系统)RY key: NULL key_len: NULL ref: NULL rows: 10 Extra: Using where1 row in set (0.00 sec)key_len
key_len列显示MySQL(和PHP搭配之最佳组合)决定使用的键长度。如果键是NULL,则长度为NULL。注意通过key_len值我们可以确定MySQL(和PHP搭配之最佳组合)将实际使用一个多部关键字的几个部分。
ref
ref列显示使用哪个列或常数与key一起从表中选择行。
rows
rows列显示MySQL(和PHP搭配之最佳组合)认为它执行查询时必须检查的行数。
Extra
该列包含MySQL(和PHP搭配之最佳组合)解决查询的详细信息。下面解释了该列可以显示的不同的文本字符串:
Distinct
MySQL(和PHP搭配之最佳组合)发现第1个匹配行后,停止为当前的行组合搜索更多的行。
Not exists
MySQL(和PHP搭配之最佳组合)能够对查询进行LEFT JIN优化,发现1个匹配LEFT JIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
当使用EXTENDED关键字时,EXPLAIN产生附加信息,可以用SHOW WARNINGS浏览。该信息显示优化器限定SELECT语句中的表和列名,重写并且执行优化规则后SELECT语句是什么样子,并且还可能包括优化过程的其它注解。
更多精彩
赞助商链接