一、基本信息
MariaDB [lots]> select @@version;
+---------------------+
| @@version |
+---------------------+
| 10.0.20-MariaDB-log |
+---------------------+
1 row in set (0.00 sec)
mysql> show variables like 'optimizer_switch';\G;
| optimizer_switch | index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=off,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on |
mysql> show create table order_test\G
*************************** 1. row ***************************
Table: order_test
Create Table: CREATE TABLE `order_test` (
`ONWAY_ID` varchar(255) DEFAULT NULL,
`CUSTOMERORDERNO` varchar(255) DEFAULT NULL,
`TOORDERNO` varchar(255) DEFAULT NULL,
`CONTRACTNO` varchar(255) DEFAULT NULL,
`EXPRESSCODE` varchar(255) DEFAULT NULL,
`EXPRESSNAME` varchar(255) DEFAULT NULL,
`EXPRESSNO` varchar(255) DEFAULT NULL,
`NODETYPE` varchar(255) DEFAULT NULL,
`ACCEPTTIME` varchar(255) DEFAULT NULL,
`ADDRESS` varchar(255) DEFAULT NULL,
`NODESTATUS` varchar(255) DEFAULT NULL,
`ACCEPTBY` varchar(255) DEFAULT NULL,
`REMARK` varchar(255) DEFAULT NULL,
`BRANCHTYPE` varchar(255) DEFAULT NULL,
`BRANCHCODE` varchar(255) DEFAULT NULL,
`BRANCHNAME` varchar(255) DEFAULT NULL,
`PACKINGORDERN` varchar(255) DEFAULT NULL,
`CONTACT` varchar(255) DEFAULT NULL,
`TEL` varchar(255) DEFAULT NULL,
KEY `order_test_ix1` (`CUSTOMERORDERNO`,`CONTRACTNO`,`TOORDERNO`,`EXPRESSNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
MariaDB [lots]> select count(*) from order_test;
+----------+
| count(*) |
+----------+
| 137591 |
+----------+
二、测试步骤
场景一:select后面是*,order by是索引字段前三个,发现不走索引
(product)root@localhost [lots]> explain select * from order_test order by CUSTOMERORDERNO,CONTRACTNO,TOORDERNO;
+----+-------------+------------+------+---------------+------+---------+------+--------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+--------+----------------+
| 1 | SIMPLE | order_test | ALL | NULL | NULL | NULL | NULL | 137305 | Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+--------+----------------+
1 row in set (0.00 sec
场景二:select后是索引第一个字段,order by后是按索引字段顺序的四个字段,发现走了覆盖索引扫描,排序字段有用到索引
(product)root@localhost [lots]> explain select CUSTOMERORDERNO from order_test order by CUSTOMERORDERNO,CONTRACTNO,TOORDERNO,EXPRESSNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
1 row in set (0.00 sec)
场景三:select后是索引第一个字段,order by后是按索引字段顺序的前三个字段,发现走了覆盖索引扫描,排序字段有用到索引
(product)root@localhost [lots]> explain select CUSTOMERORDERNO from order_test order by CUSTOMERORDERNO,CONTRACTNO,TOORDERNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
1 row in set (0.00 sec)
场景四:select后是索引第一个字段,order by后是按索引字段顺序的前第一和第二字段,发现走了覆盖索引扫描,排序字段有用到索引
(product)root@localhost [lots]> explain select CUSTOMERORDERNO from order_test order by CUSTOMERORDERNO,CONTRACTNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
1 row in set (0.00 sec)
场景五:select后是索引第一个字段,order by后是按索引字段顺序的第一字段,发现走了覆盖索引扫描,排序字段有用到索引
(product)root@localhost [lots]> explain select CUSTOMERORDERNO from order_test order by CUSTOMERORDERNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
1 row in set (0.00 sec)
---select后是索引中第二个字段,order by后是按索引字段顺序的第一字段,发现走了覆盖索引扫描,排序字段有用到索引
(product)root@localhost [lots]> explain select CONTRACTNO from order_test order by CUSTOMERORDERNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
1 row in set (0.00 sec)
场景六:select后是索引中第二和第三字段,order by后是按索引字段顺序的第一字段,发现走了覆盖索引扫描,排序字段有用到索引
(product)root@localhost [lots]> explain select CONTRACTNO,EXPRESSNO from order_test order by CUSTOMERORDERNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-------------+
1 row in set (0.00 sec)
场景七:select后是索引中第二和第三字段,order by后是按索引字段顺序的第四字段,发现走了覆盖索引扫描,但排序字段没有用到索引
(product)root@localhost [lots]> explain select CONTRACTNO,EXPRESSNO from order_test order by EXPRESSNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-----------------------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index; Using filesort |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-----------------------------+
1 row in set (0.00 sec)
场景八:select后是索引中第二和第三字段,order by后是按索引字段顺序的第一和第二字段,但排序字段没有用到索引
(product)root@localhost [lots]> explain select CONTRACTNO,EXPRESSNO from order_test order by EXPRESSNO,CONTRACTNO;
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-----------------------------+
| 1 | SIMPLE | order_test | index | NULL | order_test_ix1 | 3072 | NULL | 137305 | Using index; Using filesort |
+----+-------------+------------+-------+---------------+----------------+---------+------+--------+-----------------------------+
场景九:select后是非索引中的字段,order by后是按索引字段顺序的前三个字段,没有用到索引
(product)root@localhost [lots]> explain select NODETYPE from order_test order by CUSTOMERORDERNO,CONTRACTNO,TOORDERNO;
+----+-------------+------------+------+---------------+------+---------+------+--------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+--------+----------------+
| 1 | SIMPLE | order_test | ALL | NULL | NULL | NULL | NULL | 137305 | Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+--------+----------------+
1 row in set (0.00 sec)
总结:
1.单表排序时,排序字段只有在下面情况时,才能用到索引:order by后面字段顺序需要与复合索引中字段顺序一致
order by (c1,c2,c3,c4)、order by (c1,c2,c3)、order by (c1,c2,)和order by c1,这四种情况下,oder by才能用上索引,
顺序不同,就用不了;
2.且同时要求select后面字段要是索引字段中的一个或多个,基于这两点时排序才能用上索引。