0
点赞
收藏
分享

微信扫一扫

MySQL如何使用索引


MySQL如何使用索引?
看 这篇文章前,先看​​通过 EXPLAIN 分析低效 SQL的执行计划​​

索引用于快速找出在某个列中有一特定值的行。对相关列使用索引是提高 SELECT 操作 性能的最佳途径。 查询要使用索引最主要的条件是查询条件中需要使用索引关键字,如果是多列索引,那 么只有查询条件使用了多列关键字最左边的前缀时,才可以使用索引,否则将不能使用索引。

1.使用索引
在 MySQL 中,下列几种情况下有可能使用到索引。 (1)对于创建的多列索引,只要查询的条件中用到了最左边的列,索引一般就会被使用, 举例说明如下。 首先按company_id,moneys的顺序创建一个复合索引,具体如下:

mysql> create index ind_sales2_companyid_moneys on sales2(company_id,moneys); 
Query OK, 1000 rows affected (0.03 sec)
Records: 1000 Duplicates: 0 Warnings: 0

然后按company_id 进行表查询,具体如下: ​​mysql> explain select * from sales2 where company_id = 2006\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: sales2
type: ref
possible_keys: ind_sales2_companyid_moneys
key: ind_sales2_companyid_moneys
key_len: 5
ref: const
rows: 1
Extra: Using where

1 row in set (0.00 sec) 可以发现即便 where 条件中不是用的company_id与moneys 的组合条件,索引仍然能 用到,这就是索引的前缀特性。但是如果只按 moneys 条件查询表,那么索引就不会 被用到,具体如下: ​​mysql> explain select * from sales2 where moneys = 1\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: sales2
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using where

1 row in set (0.00 sec) (2)对于使用 like 的查询,后面如果是常量并且只有%号不在第一个字符,索引才可能会 被使用,来看下面两个执行计划: ​​mysql> explain select * from company2 where name like '%3'\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: company2
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using where
1 row in set (0.00 sec)

mysql> explain select * from company2 where name like '3%'\G;

*************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: company2
type: range
210

possible_keys: ind_company2_name
key: ind_company2_name
key_len: 11
ref: NULL
rows: 103
Extra: Using where

1 row in set (0.00 sec) 可以发现第一个例子没有使用索引,而第二例子就能够使用索引,区别就在于“%”的位置 不同,前者把“%”放到第一位就不能用到索引,而后者没有放到第一位就使用了索引。 另外,如果如果 like 后面跟的是一个列的名字,那么索引也不会被使用。 (3)如果对大的文本进行搜索,使用全文索引而不用使用 like ‘%…%’。 (4)如果列名是索引,使用 column_name is null 将使用索引。如下例中查询 name 为 null 的记录就用到了索引: ​​mysql> explain select * from company2 where name is null\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: company2
type: ref
possible_keys: ind_company2_name
key: ind_company2_name
key_len: 11
ref: const
rows: 1
Extra: Using where
1 row in set (0.00 sec)

2.存在索引但不使用索引
在下列情况下,虽然存在索引,但是 MySQL 并不会使用相应的索引。 (1) 如果 MySQL 估计使用索引比全表扫描更慢,则不使用索引。例如如果列 key_part1 均匀分布在 1 和 100 之间,下列查询中使用索引就不是很好: SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90; (2) 如果使用 MEMORY/HEAP 表并且 where 条件中不使用“=”进行索引列,那么 不会用到索引。heap 表只有在“=”的条件下才会使用索引。 (3) 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引, 那么涉及到的索引都不会被用到,例如: mysql> show index from sales\G;
*************************** 1. row ***************************

Table: sales 
Non_unique: 1
Key_name: ind_sales_year
Seq_in_index: 1
Column_name: year
211

Collation: A
Cardinality: NULL
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:

1 row in set (0.00 sec) 从上面可以发现只有 year 列上面有索引,来看如下的执行计划: ​​mysql> explain select * from sales where year = 2001 or country = 'China'\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: sales
type: ALL
possible_keys: ind_sales_year
key: NULL
key_len: NULL
ref: NULL
rows: 12
Extra: Using where

1 row in set (0.00 sec) 可见虽然在year这个列上存在索引ind_sales_year,但是这个SQL语句并没有用到这个索引, 原因就是 or 中有一个条件中的列没有索引。 (4) 如果不是索引列的第一部分,如下例子: ​​mysql> explain select * from sales2 where moneys = 1\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: sales2
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using where 1 row in set (0.00 sec)

可见虽然在 money 上面建有复合索引,但是由于 money 不是索引的第一列,那么在查询中 这个索引也不会被 MySQL 采用。 (5) 如果 like 是以%开始,例如: ​​mysql> explain select * from company2 where name like '%3'\G;​​ *************************** 1. row ***************************

id: 1 


select_type: SIMPLE
table: company2
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using where 1 row in set (0.00 sec)

可见虽然在 name 上建有索引,但是由于 where 条件中 like 的值的“%”在第一位了,那么 MySQL 也不会采用这个索引。 (6) 如果列类型是字符串,那么一定记得在 where 条件中把字符常量值用引号引 起来,否则的话即便这个列上有索引,MySQL 也不会用到的,因为,MySQL 默认把输入的 常量值进行转换以后才进行检索。如下面的例子中company2表中的name字段是字符型的, 但是 SQL 语句中的条件值 294 是一个数值型值,因此即便在 name 上有索引,MySQL 也不能 正确地用上索引,而是继续进行全表扫描。 ​​mysql> explain select * from company2 where name = 294\G;​​ *************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: company2
type: ALL
possible_keys: ind_company2_name
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using where
1 row in set (0.00 sec)

mysql> explain select * from company2 where name = '294'\G;

*************************** 1. row ***************************

id: 1 
select_type: SIMPLE
table: company2
type: ref
possible_keys: ind_company2_name
key: ind_company2_name
key_len: 23
ref: const
rows: 1
Extra: Using where
1 row in set (0.00 sec)

从上面的例子中可以看到,第一个 SQL 语句中把一个数值型常量赋值给了一个字符型的列 name,那么虽然在 name 列上有索引,但是也没有用到;而第二个 SQL 语句就可以正确使 用索引


举报

相关推荐

0 条评论