Mysql索引會失效的幾種情況分析

Mysql索引會失效的幾種情況分析

CREATE TABLE `members` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用戶名',
  `password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密碼',
  `qq` int(10) DEFAULT NULL COMMENT '密碼',
  `register_ip` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '註冊IP',
  `wechat` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`),
  UNIQUE KEY `password` (`password`(191)) USING BTREE,
  KEY `qq` (`qq`)
) ENGINE=MyISAM AUTO_INCREMENT=286 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


1.explain 查看索引使用

在這裏插入圖片描述

  • type列,連接類型。一個好的SQL語句至少要達到range級別。杜絕出現all級別。
  • possible_keys:顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引獎盃列出,但不一定被查詢實際使用。
  • key列,使用到的索引名。如果沒有選擇索引,值是NULL。可以採取強制索引方式。
  • key_len列,索引長度。
  • rows列,掃描行數。該值是個預估值。
  • extra列,詳細說明。注意,常見的不太友好的值,如下:Using filesort,Using temporary。

各列表的值詳情:https://www.cnblogs.com/miskis/p/9081187.html

1.1type類型
type 解釋
null
system const的特例,僅返回一條數據的時候。
const 查找主鍵索引,返回的數據至多一條(0或者1條)。 屬於精確查找
eq_ref 查找唯一性索引,返回的數據至多一條。屬於精確查找
ref 查找非唯一性索引,返回匹配某一條件的多條數據。屬於精確查找、數據返回可能是多條
range 查找某個索引的部分索引,一般在where子句中使用 < 、>、in、between等關鍵詞。只檢索給定範圍的行,屬於範圍查找
index 查找所有的索引樹,比ALL要快的多,因爲索引文件要比數據文件小的多。
ALL 不使用任何索引,進行全表掃描,性能最差。

從下到上逐漸變好,使用的索引至少要達到range 級別。

2.使用or / !=(<>) / not null / is null

or影響

mysql> explain select * from members where name = '1' or wechat = '1';
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys      | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | members | ALL  | name,name_password | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
!=
mysql> explain select * from members where name != '1';
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys      | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | members | ALL  | name,name_password | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
is null
mysql> explain select * from members where name is not null;
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys      | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | members | ALL  | name,name_password | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
is not null
mysql> explain select * from members where name is not null;
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys      | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | members | ALL  | name,name_password | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+

3. 字符串類型,where的時候帶引號

mysql> explain select * from members where name = '1';
+----+-------------+---------+-------+--------------------+------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys      | key  | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+--------------------+------+---------+-------+------+-------+
|  1 | SIMPLE      | members | const | name,name_password | name | 402     | const |    1 |       |
+----+-------------+---------+-------+--------------------+------+---------+-------+------+-------+
1 row in set

mysql> explain select * from members where name = 1;
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys      | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | members | ALL  | name,name_password | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+---------+------+--------------------+------+---------+------+------+-------------+

4. 不建議使用%前綴模糊查詢

例如LIKE“%name”或者LIKE“%name%”,這種查詢會導致索引失效而進行全表掃描。
但是可以使用LIKE “name%”。

mysql> explain select name from members where name like '%1';
+----+-------------+---------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type | table   | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+-------------+---------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | SIMPLE      | members | index | NULL          | name | 402     | NULL |    2 | Using where; Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+--------------------------+
1 row in set

mysql> explain select name from members where name like '1%';
+----+-------------+---------+-------+--------------------+------+---------+------+------+--------------------------+
| id | select_type | table   | type  | possible_keys      | key  | key_len | ref  | rows | Extra                    |
+----+-------------+---------+-------+--------------------+------+---------+------+------+--------------------------+
|  1 | SIMPLE      | members | index | name,name_password | name | 402     | NULL |    2 | Using where; Using index |
+----+-------------+---------+-------+--------------------+------+---------+------+------+--------------------------+

那如何查詢%name%?答案:使用全文索引。

# 更新全文索引
ALTER TABLE `members` ADD FULLTEXT INDEX `name` (`name`);
mysql> explain select name from members where match(name) against ('1' in boolean mode);
+----+-------------+---------+----------+---------------+------+---------+-----+------+-------------+
| id | select_type | table   | type     | possible_keys | key  | key_len | ref | rows | Extra       |
+----+-------------+---------+----------+---------------+------+---------+-----+------+-------------+
|  1 | SIMPLE      | members | fulltext | name          | name | 0       |     |    1 | Using where |
+----+-------------+---------+----------+---------------+------+---------+-----+------+-------------+

5.索引列上少計算

不在索引列上做任何操作(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描
其中後面那句varchar引號不能丟也是如此,如果是丟了,則會進行自動類型轉換,就相當於計算。

待續。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章