MySQL索引_組合索引和單列索引

何時使用組合索引,何時使用單獨索引

一.前期數據準備
1.建表
CREATE TABLE `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `pwd` varchar(50) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `rids` varchar(15) DEFAULT NULL,
  `nickname` varchar(45) DEFAULT NULL,
  `company` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`uid`),
  UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
2.插入數據
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (1, 'rocker', 'rocker', NULL, '2019-10-08 11:05:02', '1', 'rocker', 'rocker');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (2, 'danny', 'danny', NULL, '2019-10-08 11:31:36', '2', 'rocker', 'danny');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (3, 'tom', 'tom', NULL, '2019-10-08 11:31:39', '1', 'tom', 'rocker');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (4, 'messi', 'messi', NULL, '2019-10-08 11:31:21', '2', 'messi', 'messi');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (5, 'wenger', 'wenger', NULL, '2019-10-08 11:29:38', '1', 'wenger', 'rocker');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (6, 'henry', 'henry', NULL, '2019-10-08 11:30:46', '2', 'henry', 'henry');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (7, 'ronaldo', 'ronaldo', NULL, '2019-10-08 11:30:49', '1', 'ronaldo', 'ronaldo');
INSERT INTO `monitor`.`user`(`uid`, `name`, `pwd`, `create_time`, `modify_time`, `rids`, `nickname`, `company`) VALUES (8, 'kaka', 'kaka', NULL, '2019-10-08 11:29:45', '2', 'kaka', 'rocker');
二.分析
1.不加索引

首先在'nickname'和‘company’這倆字段不加索引的狀況下執行一個查詢語句,並分析mysql

mysql> explain select * from user where nickname = 'rocker' and company = 'rocker';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    8 |    12.50 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

能夠看到,沒有走索引,總共查詢了8條數據,而表中總共也是8條數據,至關於全表掃描了。sql

mysql> explain select * from user where company = 'rocker' or nickname = 'rocker';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    8 |    23.44 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

能夠看到:不加任何索引的狀況下,無論是and仍是or,都是全表掃描,沒有索引。ui

2.單獨索引

給nickname和company分別加上索引,再執行and和or的sql查詢code

alter table user add index `idx_nickname` (`nickname`);
alter table user add index `idx_company` (`company`);

執行查詢語句and排序

mysql> explain select * from user where nickname = 'rocker' and company = 'rocker';
+----+-------------+-------+------+--------------------------+--------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys            | key          | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+--------------------------+--------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_nickname,idx_company | idx_nickname | 138     | const |    2 | Using where |
+----+-------------+-------+------+--------------------------+--------------+---------+-------+------+-------------+
1 row in set (0.05 sec)

執行查詢語句or索引

mysql> explain select * from user where company = 'rocker' or nickname = 'rocker';
+----+-------------+-------+------+--------------------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys            | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+--------------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | idx_nickname,idx_company | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+--------------------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

能夠看到:加上索引後and查詢是能夠走索引的,可是隻有一個索引發做用,對於另外一個索引字段仍是要進行遍歷,並且and查詢會根據關聯性高(符合該條件的行數少)選擇具體走哪一個索引it

or查詢不走索引io

3.組合索引

刪除原先的單獨索引,新增組合索引table

alter table user drop index `idx_nickname`
alter table user drop index `idx_company`

alter table user add index `idx_composition` (`nickname`,`company`);

執行查詢語句andclass

mysql> explain select * from user where nickname = 'rocker' and company = 'rocker';
+----+-------------+-------+------+-----------------+-----------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref         | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_composition | idx_composition | 186     | const,const |    1 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

執行查詢語句or

mysql> explain select * from user where company = 'rocker' or nickname = 'rocker';
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys   | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | idx_composition | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

能夠看到:加上組合索引後,組合索引發做用,只需查詢一條符合結果的數據,效率要比單獨索引高,

可是複合索引對於or查詢不起做用

4.組合索引查詢單個索引列

對於組合索引爲(nickname,company)這個順序的狀況

alter table user drop index `idx_composition`;

alter table user add index `idx_composition` (`nickname`,`company`);
mysql> explain select * from user where nickname = 'rocker';
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_composition | idx_composition | 138     | const |    2 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where company = 'rocker';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

能夠看到:組合索引中nickname在前時,單獨查詢nickname會走索引,單獨查詢compamy不會走索引

對於組合索引爲(company,nickname)這個順序的狀況

alter table user drop index `idx_composition`;

alter table user add index `idx_composition` (`company`,`nickname`);
mysql> explain select * from user where nickname = 'rocker';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from user where company = 'rocker';
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user  | ref  | idx_composition | idx_composition | 48      | const |    2 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

能夠看到:組合索引中compamy在前時,單獨查詢compamy會走索引,單獨查詢nickname不會走索引

若是組合索引是(A,B),則對於條件A=a,是能夠用上這個組合索引的,由於組合索引是先按照第一列進行排序的,因此不必對A單獨創建一個索引,可是對於B=b就用不上了,由於只有在第一列相同的狀況下,才比較第二列,於是第二列相同的,能夠分佈在不一樣的節點上,沒辦法快速定位

相關文章
相關標籤/搜索