转载自: https://www.cnblogs.com/phpdragon/p/8231533.html,实践如下
主键索引和普通索引
mysql> show create table test_user;
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_user | CREATE TABLE `test_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL,
`password` varchar(32) DEFAULT NULL,
`status` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10000001 DEFAULT CHARSET=utf8 |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
- 查看表索引
如下是个主键索引
mysql> SHOW INDEX FROM test_user;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_user | 0 | PRIMARY | 1 | id | A | 9702644 | NULL | NULL | | BTREE | | |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
mysql>
- 1千万条数据
select count(*)
需要2sec多
mysql> select count(*) from test_user;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
1 row in set (2.06 sec)
mysql> select count(*) from test_user;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
1 row in set (2.08 sec)
mysql>
- sql 主键 与 非主键 查询
mysql> EXPLAIN SELECT id,username,email,password FROM sample_data.test_user WHERE id=999999;
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | test_user | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT id,username,email,password FROM test_user WHERE username='username_9000000';
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | test_user | ALL | NULL | NULL | NULL | NULL | 9702644 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
mysql>
- 查询时间
mysql> SELECT id,username,email,password FROM test_user WHERE username='username_9000000';
+---------+------------------+----------------+----------------------------------+
| id | username | email | password |
+---------+------------------+----------------+----------------------------------+
| 9000000 | username_9000000 | 9000000@qq.com | 48e4e6ac22db9be84820222d57841428 |
+---------+------------------+----------------+----------------------------------+
1 row in set (3.02 sec)
mysql> SELECT id,username,email,password FROM sample_data.test_user WHERE id=999999;
+--------+-----------------+---------------+----------------------------------+
| id | username | email | password |
+--------+-----------------+---------------+----------------------------------+
| 999999 | username_999999 | 999999@qq.com | 52c69e3a57331081823331c4e69d3f2e |
+--------+-----------------+---------------+----------------------------------+
1 row in set (0.00 sec)
mysql>
- 给 usename 建立索引
mysql> ALTER TABLE `test_user` ADD INDEX index_name(username) ;
Query OK, 0 rows affected (27.21 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW INDEX FROM test_user;
+-----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_user | 0 | PRIMARY | 1 | id | A | 9702644 | NULL | NULL | | BTREE | | |
| test_user | 1 | index_name | 1 | username | A | 9702644 | NULL | NULL | YES | BTREE | | |
+-----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
mysql>
- 对普通字段建立索引后查询
mysql> EXPLAIN SELECT id,username,email,password FROM test_user WHERE username='username_9000000';
+----+-------------+-----------+------+---------------+------------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------------+---------+-------+------+-----------------------+
| 1 | SIMPLE | test_user | ref | index_name | index_name | 153 | const | 1 | Using index condition |
+----+-------------+-----------+------+---------------+------------+---------+-------+------+-----------------------+
1 row in set (0.01 sec)
mysql> SELECT id,username,email,password FROM test_user WHERE username='username_9000000';
+---------+------------------+----------------+----------------------------------+
| id | username | email | password |
+---------+------------------+----------------+----------------------------------+
| 9000000 | username_9000000 | 9000000@qq.com | 48e4e6ac22db9be84820222d57841428 |
+---------+------------------+----------------+----------------------------------+
1 row in set (0.00 sec)
mysql>
- and or 有索引的区别
mysql> SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' OR username = 'username_900000';
+--------+-----------------+---------------+----------------------------------+
| id | username | email | PASSWORD |
+--------+-----------------+---------------+----------------------------------+
| 24601 | username_24601 | 24601@qq.com | 7ece221bf3f5dbddbe3c2770ac19b419 |
| 900000 | username_900000 | 900000@qq.com | c3c4f8c964d8fbd9ce62ff3921bd5e79 |
+--------+-----------------+---------------+----------------------------------+
2 rows in set (3.42 sec)
mysql> SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000';
Empty set (0.01 sec)
mysql>
and语句中,username有索引,优先使用了索引
or语句中,username有索引,但是password是没有索引的,or语句还是扫描全部数据,所以很耗时
mysql> explain SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000';
+----+-------------+-----------+------+---------------+------------+---------+-------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------------+---------+-------+------+------------------------------------+
| 1 | SIMPLE | test_user | ref | index_name | index_name | 153 | const | 1 | Using index condition; Using where |
+----+-------------+-----------+------+---------------+------------+---------+-------+------+------------------------------------+
1 row in set (0.00 sec)
mysql> explain SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' OR username = 'username_900000';
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | test_user | ALL | index_name | NULL | NULL | NULL | 9702644 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
mysql>
聚合索引
mysql> ALTER TABLE `test_user` ADD INDEX index_union_name_password(username,password);
Query OK, 0 rows affected (33.63 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW INDEX FROM test_user;
+-----------+------------+---------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+---------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_user | 0 | PRIMARY | 1 | id | A | 9702644 | NULL | NULL | | BTREE | | |
| test_user | 1 | index_name | 1 | username | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password | 1 | username | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password | 2 | password | A | 9702644 | NULL | NULL | YES | BTREE | | |
+-----------+------------+---------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)
mysql>
- or 在聚合索引中无效
mysql> SELECT id, username, email, PASSWORD FROM test_user WHERE username = 'username_900000' OR `password` = '7ece221bf3f5dbddbe3c2770ac19b419';
+--------+-----------------+---------------+----------------------------------+
| id | username | email | PASSWORD |
+--------+-----------------+---------------+----------------------------------+
| 24601 | username_24601 | 24601@qq.com | 7ece221bf3f5dbddbe3c2770ac19b419 |
| 900000 | username_900000 | 900000@qq.com | c3c4f8c964d8fbd9ce62ff3921bd5e79 |
+--------+-----------------+---------------+----------------------------------+
2 rows in set (3.45 sec)
mysql> explain SELECT id, username, email, PASSWORD FROM test_user WHERE username = 'username_900000' OR `password` = '7ece221bf3f5dbddbe3c2770ac19b419';
+----+-------------+-----------+------+--------------------------------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+--------------------------------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | test_user | ALL | index_name,index_union_name_password | NULL | NULL | NULL | 9702644 | Using where |
+----+-------------+-----------+------+--------------------------------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
mysql>
- and 使用了聚合索引
mysql> SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000';
Empty set (0.00 sec)
mysql> explain SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000';
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
| 1 | SIMPLE | test_user | ref | index_name,index_union_name_password | index_name | 153 | const | 1 | Using index condition; Using where |
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
1 row in set (0.00 sec)
mysql>
mysql> SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000' \
-> and status = 0;
Empty set (0.00 sec)
mysql> explain SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000' and status = 0;
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
| 1 | SIMPLE | test_user | ref | index_name,index_union_name_password | index_name | 153 | const | 1 | Using index condition; Using where |
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
1 row in set (0.00 sec)
mysql>
mysql> explain SELECT id, username, email, PASSWORD FROM test_user WHERE status = 0 and `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and username = 'username_900000';
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
| 1 | SIMPLE | test_user | ref | index_name,index_union_name_password | index_name | 153 | const | 1 | Using index condition; Using where |
+----+-------------+-----------+------+--------------------------------------+------------+---------+-------+------+------------------------------------+
1 row in set (0.00 sec)
mysql>
AND 语句才使用到了聚合索引,聚合索引必须使用AND条件,同时要符合最左原则
- 最左索引 例子
mysql> ALTER TABLE `test_user` ADD INDEX index_union_name_password_status(username,password,status);
Query OK, 0 rows affected (33.51 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW INDEX FROM test_user;
+-----------+------------+----------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test_user | 0 | PRIMARY | 1 | id | A | 9702644 | NULL | NULL | | BTREE | | |
| test_user | 1 | index_name | 1 | username | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password | 1 | username | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password | 2 | password | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password_status | 1 | username | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password_status | 2 | password | A | 9702644 | NULL | NULL | YES | BTREE | | |
| test_user | 1 | index_union_name_password_status | 3 | status | A | 9702644 | NULL | NULL | YES | BTREE | | |
+-----------+------------+----------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
7 rows in set (0.00 sec)
mysql>
如下的sql不会使用到索引
explain SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419';
explain SELECT id, username, email, PASSWORD FROM test_user WHERE `password` = '7ece221bf3f5dbddbe3c2770ac19b419' and status = 0;
如下的语句则会使用索引
explain SELECT id, username, email, PASSWORD FROM test_user WHERE `username` = '999999' and status = 0;