Mysql教程

18.2优化查询

査询是数据库中最频繁的操作。提高了查询速度可以有效的提高MySQL数据库的性能。本节将为读者介绍优化査询的方法。

18.2.1分析查询语句

通过对查洵语句的分析,可以了解查询语句的执行情况。MySQL中,可以使用EXPLAIN语句和DESCRIBE语句来分析查询语句。本小节将为读者介绍这两种分析查询 语句的方法。

EXPLAIN语句的基本语法如下:

EXPLAIN SELECT 语句;

通过EXPLAIN关键字可以分析后面的SELECT语句的执行情况。并且能够分析出所査询的表的一些内容。

【示例18-1】下面使用EXPLAIN语句来分析一个查询语句。代码执行如下:

mysql> EXPLAIN SELECT * FROM student \G
id:1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 6
Extra:
1 row in set (0.01 sec)

查询结果显示了id、select_type>、table、type、possible_keys和key等信息。下面分別进行解释。


  • id:表示SELECT语句的编号


  • select_type:表示SELECT语句的类型。该参数有几个常用的取值,即SIMP;E表示简单查询,其中不包括连接查询和子查询;PRIMARY表示主查询,或者是最外层的査询语句;UNION表示连接查询的第二个或后面的查询语句;


  • table:表示查询的表


  • type:表示表的连接类型。该参数有几个常用的取值,即system表示表中只有一条记录;const表示表中有多条记录,但只从表中查询一条记录;ALL表示对表进行了完整的扫描;eq_ref表示多表连接时,后面的表使用了UNlQUE或者PRIMARY KEY;ref表示多表查询时,后面的表使用了普通索引;unique_subquery表示子查询中使用了UNlQUE或者PRIMARY KEY;index_subquery表示子查询中使用了普通索引;range表示查询语句中给出了查询范围;index表示对表中的索引进行了完整的扫描


  • possible_keys:表示查询中可能使用的索引


  • key:表示查询使用到的索引


  • key_len:表示索引字段的长度


  • ref:表示使用哪个列或常数与索引一起来查询记录


  • rows:表示查询的行数


  • Extra:表示查询过程的附件信息

DESCRIBE语句的使用方法与EXPLAIN语句是一样的。这两者的分析结果也是一样的。DESCRIBE语句的语法形式如下:

DESCRIBE SELECT 语句;

DESCRIBE可以缩写成DESC。

18.2.2 索引对查询速度的影响

索引可以快速的定位表中的某条记录。使用索引可以提高数据库查询的速度,从而提高数据库的性能。本小节将为读者介绍索引对查询速度的影响。 如果查询时不使用索引,查询语句将查询表中的所有字段。这样查询的速度会很慢。 如果使用索引进行查询,查询语句只查询索引字段。这样可以减少查询的记录数,达到提高查询速度的目的。

【示例18-2】下面是查询语句中不使用索引和使用索引的对比。现在分析未使用索引时的查询情况,EXPLAIN语句执行如下:

mysql> EXPLAIN SELECT * FROM student WHERE name='张三' \G
***********************1.row***********************
id:i
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
reT. NULL
rows: 6
Extra: Using where
1 row in set(0.00 sec)

结果显示,rows参数的值为6。这说明这个查询语句查询了6条记录。现在在name字段上建立一个名为index_name的索引。CREATE语句执行如下:

现在,name字段上已经有索引了,然后再分析查询语句的执行情况。EXPLAIN语句执行如下:

mysql> EXPLAIN SELECT * FROM student WHERE name='张三' \G
**************************1.row*******************
id: 1
select_type: SIMPLE
table: student
type: ref
possible_keys:index_name
key:index_name
key_len:22
ref:const
Extra:Using where
1 row in set(0.00 sec)

结果显示,rows参数的值为1。这表示这个查询语句只查询了一条记录,其查询速度自然比查询6条记录快。而且possible_keys和key的值都是index_name,这说明查询时使用了index_name索引。

18.2.3使用索引查询

索引可以提高查询的速度。但是有些时候即使查询时使用的是索引,但索引并没有起作用。本小节将向读者介绍索引的使用。

1.查询语句中使用口LIKE关键字

在查询语句中使用LIKE关键字进行查询时,如果匹配字符串的第一个字符为“%” 时,索引不会被使用。如果“%”不是在第一个位置,索引就会被使用。

【示例18-3】下面查询语句中使用LIKE关键字,并且匹配的字符串中含有“%”符 号。EXPLAIN语句执行如下:

mysql> EXPLAIN SELECT * FROM student WHERE name LIKE,'%四' \G
************************1.row**********************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 6
Extra: Using where 1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM student WHERE name LIKE '李%' \G
******************1. row ***************************
select_type: SIMPLE
table: student
type: range
possible_keys: index_name
key: index_name
key_len: 22
ref: NULL
rows: 1
Extra: Using where 1 row in set (0.00 sec)

第一个查询语句执行后,rows参数的值为6,表示这次查询过程中查询了6条记录:第二个查询语句执行后,rows参数的值为l,表示这次查询过程只查询一条记录。同样是 使用的name字段进行查询,第一个查询语句没有使用索引,而第二个查洵语句使用了索引index_name。因为第一个查询语句的LIKE关键字后的字符串以“%”开头。

2. 查询语句中使用多列索引

多列索引是在表的多个字段上创建一个索引。只有査询条件中使用了这些字段中第一个字段时,索引才会被使用。

【示例18-4】下面在birth和department两个字段上创建多列索引,然后验证多列索引的使用情况。

mysql> CREATE INDEX index_birth_department ON student(birth,department);
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> EXPLAIN SELECT * FROM student WHERE birth=1991 \G
*******************1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ref
possible_keys: index_birth_department
key: index_birth_department
key_len: 2
ref: const
rows: 1
Extra: Using where 1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM student WHERE department='英语系' \G
********************1.row******************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 6
Extra: Using where 1 row in set (0.00 sec)

在birth字段和department字段上创建一个多列索引。第一个查询语句的查询条件使用了 birth字段,分析结果显示rows参数的值为1。而且显示查询过程中使用了index_birth_department索引。第二个査询语句的查询条件使用了department字段,结果显示rows参数的值为6。而且key参数的值为NULL,这说明第二个查询语句没有使用索引。因为name字段是多列索引的第一个字段,只有査询条件中使用 name字段才会使index_name_department 索引起作用。


3.查询语句中使用OR关键字

査询语句只有OR关键字时,如果OR前后的两个条件的列都是索引时,查询中将使用索引。如果OR前后有一个条件的列不是索引,那么査询中将不使用索引。


【示例18-5】下面演示OR关键字的使用。

mysql> EXPLAIN SELECT * FROM student WHERE name='张三' or  sex='女' \G
****************1.row*****************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: index_name
key: NULL
key_len: NULL
ref: NULL
rows: 6
Extra: Using where 1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM student WHERE name='张三' or  sex='女' \G
****************1.row*****************
id: 1
select_type: SIMPLE
table: student
type: index_merge
possible_keys: PRIMARY,id,index_name
key: index_name,PRIMARY key_len: 22,4
ref: NULL rows: 2
Extra: Using union(index_name,PRIMARY); Using where
row in set (0.00 sec)

第一个查询语句没有使用索引,因为sex字段上没有索引;第二个查询语句使用了index_name和PRIMARY这两个索引’因为name字段和id字段上都有索引。

技巧:使用索引查询记录时,一定要注意索引的使用情况。例如,LlKE关键字配置的字符串不能以“%”开头;使用多列索引时,查询条件必须要使用这个索引的第一个字段;使用or关键字时,or关键字连接的所有条件都必须使用索引。

18.2.4优化子查询

很多查询中需要使用子査询。子查询可以使查询语句很灵活,但子查询的执行效率不高。子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句再临时表中查询记录。査询完毕后,MySQL需要撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。在MySQL 中可以使用连接查询来替代子査询。连接査询不需要建立临时表,其速度比子查询要快。



关注微信获取最新动态