测试mysql单表排序是否有走索引

一、基本信息
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后面字段要是索引字段中的一个或多个,基于这两点时排序才能用上索引。

你可能感兴趣的:(mysql性能优化)