热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何进行MySQL中的orderby优化

这篇文章将为大家详细讲解有关如何进行MySQL中的orderby优化,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关

这篇文章将为大家详细讲解有关如何进行MySQL中的order by 优化,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

一 前言 
   介绍order by 的基本原理以及优化。如果觉得对order by原理了解不透彻,看完之后你可以了解到什么样的select + order by 语句可以使用索引,什么样的不能利用到索引排序。
二 分析  
2.1 官方标准介绍
对于select  order by语句如何能够利用到索引,官方表述如下:

  1. "The index can also be used even if the ORDER BY does not match the index exactly, as long as all of the unused portions of the index and all the extra ORDER BY columns are constants in the WHERE clause."

翻译一下就是
即使ORDER BY语句不能精确匹配(组合)索引列也能使用索引,只要WHERE条件中的所有未使用的索引部分和所有额外的ORDER BY列为常数就行。
如何理解这句话呢?我们通过具体用例来解释。
2.2 准备工作

  1. CREATE TABLE `tx` (

  2.   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '记录ID',

  3.   `shid` int(11) NOT NULL COMMENT '商店ID',

  4.   `gid` int(11) NOT NULL COMMENT '物品ID',

  5.   `type` tinyint(1) NOT NULL COMMENT '支付方式',

  6.   `price` int(10) NOT NULL COMMENT '物品价格',

  7.   `comment` varchar(200) NOT NULL COMMENT '备注',

  8.   PRIMARY KEY (`id`),

  9.   UNIQUE KEY `uniq_shid_gid` (`shid`,`gid`),

  10.   KEY `idx_price` (`price`),

  11.   KEY `idx_type` (`type`)

  12. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ;

  13. INSERT INTO `tx` (`shid`, `gid`, `type`, `price`, `comment`) VALUES (6, 2, 0, '399', '2'),(6, 5, 0, '288', '2'),(6, 11, 0, '10', '2');

  14. (1, 1, 0, '10', 'sd'),

  15. (2, 55, 0, '210', 'sa'),

  16. (2, 33, 1, '999', 'a'),

  17. (3, 17, 0, '198', 'b'),

  18. (3, 22, 1, '800', 'e'),

  19. (4, 12, 0, '120', 'f'),

  20. (4, 73, 0, '250', 'd'),

  21. (5, 61, 0, '10', 'c'),

  22. (6, 1, 0, '210', '2'),

  23. (7, 9, 1, '999', '44'),

  24. (7, 2, 0, '198', '45'),

  25. (8, 3, 1, '800', 'rt'),

  26. (9, 4, 0, '120', 'pr'),

  27. (9, 6, 0, '250', 'x'),

  28. (10, 8, 0, '10', 'w'),

  29. (12, 9, 0, '210', 'w'),

  30. (12, 10, 1, '999', 'q'),

  31. (13, 11, 0, '198', ''),

  32. (13, 12, 1, '800', ''),

  33. (14, 13, 0, '120', ''),

  34. (14, 19, 0, '250', '');

  35. CREATE TABLE `goods_type` (

  36.   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',

  37.   `type` int NOT NULL COMMENT '类型',

  38.   `name` varchar(20) NOT NULL COMMENT '名称',

  39.   PRIMARY KEY (`id`)

  40. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

  41. INSERT INTO `goods_type` (`id`, `type`, `name`) VALUES

  42. (1, 1, 'hw手机'),

  43. (2, 0, 'xiaomi'),

  44. (3, 1, 'apple')


2.3 能够利用索引的例子分析
官方的文档 中介绍有7个例子可以使用索引进行排序。如果使用explain/desc工具查看执行计划中的extra中出现了Using filesort则说明sql没有用到排序优化。
案例一
文档: SELECT * FROM t1 ORDER BY key_part1,key_part2,...; 

  1. test [RW] 06:03:52 >desc select * from tx order by  shid,gid;

  2. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  3. | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |

  4. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  5. | 1  | SIMPLE      | tx    | ALL  | NULL          | NULL | NULL    | NULL | 24   | Using filesort |

  6. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  7. 1 row in set (0.00 sec)

分析:
  显然上述sql没有利用到索引排序. type=ALL Extra=Using filesort,因为where字句没有条件,优化器选择全表扫描和内存排序。

  1. test [RW] 06:04:39 >desc select gid from tx order by  shid,gid;

  2. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  3. | id | select_type | table | type  | possible_keys | key         | key_len   | ref  | rows | Extra       |

  4. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  5. | 1  | SIMPLE      | tx    | index | NULL          | uniq_shid_gid | 8       | NULL | 24   | Using index |

  6. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  7. 1 row in set (0.00 sec)

  8. test [RW] 06:04:47 >desc select shid,gid from tx order by  shid,gid;

  9. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  10. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra |

  11. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  12. | 1  | SIMPLE      | tx    | index | NULL          | uniq_shid_gid | 8       | NULL | 24   | Using index |

  13. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  14. 1 row in set (0.00 sec)

  15. test [RW] 06:04:54 >desc select id,shid,gid from tx order by  shid,gid;

  16. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  17. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra |

  18. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  19. | 1  | SIMPLE      | tx    | index | NULL          | uniq_shid_gid | 8       | NULL | 24   | Using index |

  20. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  21. 1 row in set (0.00 sec)

分析
    从type=index,extra=Using index 可以看出当select 的字段包含在索引中时,能利用到索引排序功能,进行覆盖索引扫描。
    使用select * 则不能利用覆盖索引扫描且由于where语句没有具体条件MySQL选择了全表扫描且进行了排序操作。
案例二
  SELECT * FROM t1 WHERE key_part1 = constant ORDER BY key_part2;
使用组合索引中的一部分做等值查询 ,另一部分作为排序字段。更严谨的说法是where条件使用组合索引的左前缀等值查询,使用剩余字段进行order by排序。

  1. test [RW] 06:05:41 >desc select * from tx where shid= 2 order by  gid;

  2. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  3. | id | select_type | table | type | possible_keys | key | key_len | ref     | rows  | Extra|

  4. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  5. | 1  | SIMPLE      | tx    | ref  | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | Using where |

  6. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  7. 1 row in set (0.00 sec)

  8. test [RW] 11:30:13 >desc select * from tx where shid= 2 order by  gid desc;

  9. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  10. | id | select_type | table | type | possible_keys | key | key_len | ref     | rows  | Extra|

  11. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  12. | 1  | SIMPLE      | tx    | ref  | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | Using where |

  13. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  14. 1 row in set (0.00 sec)

分析:
  where 条件字句可以基于 shid 进行索引查找 并且利用(shid,gid)中gid的有序性避免额外的排序工作. 我们基于本例解释"即使ORDER BY语句不能精确匹配(组合)索引列也能使用索引,只要WHERE条件中的所有未使用的索引部分和所有额外的ORDER BY列为常数就行。"
该语句的order by  gid 并未精确匹配到组合索引(shid,gid),where条件 shid利用了组合索引的最左前缀且为等值常量查询,对order by 而言shid就是额外的字段,没有出现在order by子句中却是组合索引的一部分。这样的条件既可以使用索引来排序。

案例三
SELECT * FROM t1  ORDER BY key_part1 DESC, key_part2 DESC;
其实和案例一 类似,只是选择了倒序。该sql不能利用索引的有序性,需要server层进行排序。

  1. test [RW] 06:06:30 >desc select * from tx order by shid desc,gid desc;

  2. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  3. | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |

  4. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  5. | 1  | SIMPLE      | tx    | ALL  | NULL          | NULL | NULL    | NULL | 24   | Using filesort |

  6. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  7. 1 row in set (0.00 sec)

  8. 如果select 中选择索引字段,可以利用覆盖索引扫描则可以利用索引进行排序。

  9. test [RW] 06:06:31 >desc select shid,gid from tx order by shid desc,gid desc;

  10. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  11. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra       |

  12. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  13. | 1  | SIMPLE      | tx    | index | NULL          | uniq_shid_gid | 8       | NULL | 24   | Using index |

  14. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+

  15. 1 row in set (0.00 sec)

案例四
SELECT * FROM t1 WHERE key_part1 = 1  ORDER BY key_part1 DESC, key_part2 DESC;
本例和案例二类似,只是order by 字句中包含所有的组合索引列。

  1. test [RW] 06:06:55 >desc select * from tx where shid=4 order by shid desc ,gid desc;

  2. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  3. | id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra       |

  4. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  5. | 1  | SIMPLE      | tx    | ref  | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | Using where |

  6. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

  7. 1 row in set (0.00 sec)

分析:
   where shid=4 可以利用shid的索引定位数据记录,select *  有不在索引里面的字段,所以回表访问组合索引列之外的数据,利用了gid索引的有序性避免了排序工作。
案例五
SELECT * FROM t1 WHERE key_part1 > constant ORDER BY key_part1 ASC;
SELECT * FROM t1 WHERE key_part1

  1. test [RW] 11:40:48 >desc select * from tx where  shid>5 order by shid desc ;

  2. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+

  3. | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                       |

  4. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+

  5. | 1  | SIMPLE      | tx    | ALL  | uniq_shid_gid | NULL | NULL    | NULL | 24   | Using where; Using filesort |

  6. +----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+

  7. 1 row in set (0.00 sec)


  8. test [RW] 11:47:25 >desc select * from tx where  shid>13 order by shid desc ;

  9. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-----------------------+

  10. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                 |

  11. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-----------------------+

  12. | 1  | SIMPLE      | tx    | range | uniq_shid_gid | uniq_shid_gid | 4       | NULL | 2    | Using index condition |

  13. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-----------------------+

  14. 1 row in set (0.00 sec)

分析
  表总共24行,其中大于5的有16行,大于13的2行,导致MySQL优化器选择了不同的执行计划。这个测试说明和shid的区分度有关。
案例六
SELECT * FROM t1 WHERE key_part1 = constant1 AND key_part2 > constant2 ORDER BY key_part2;
利用组合索引前缀索引进行ref等值查询,其他字段进行范围查询,order by 非等值的字段

  1. test [RW] 06:10:41 >desc select * from tx where shid=6 and gid>1  order by gid;

  2. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-----------------------+

  3. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                 |

  4. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-----------------------+

  5. | 1  | SIMPLE      | tx    | range | uniq_shid_gid | uniq_shid_gid | 8       | NULL | 3    | Using index condition |

  6. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-----------------------+

  7. 1 row in set (0.02 sec)

分析:
    利用shid=6的进行索引查询记录到了MySQL的ICP特性,无排序操作。为啥使用ICP 这个待确认。

2.4 不能利用索引排序的分析
案例一
order by语句使用了多个不同的索引
SELECT * FROM t1 ORDER BY key1, key2;

  1. test [RW] 09:44:03 >desc select * from tx  order by  price, type;

  2. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  3. | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |

  4. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  5. | 1  | SIMPLE      | tx    | ALL  | NULL          | NULL | NULL    | NULL | 24   | Using filesort |

  6. +----+-------------+-------+------+---------------+------+---------+------+------+----------------+

  7. 1 row in set (0.00 sec)

因为sql使用了不同的索引列,在存储上顺序存在不一致的可能性,MySQL会选择排序操作。
特例 因为所有的辅助索引里面都包含主键id,当where 字段加上order by字段沟通完整的索引时 ,可以避免filesort的

  1. test [RW] 11:20:10 >desc select * from tx where type=1 order by  id;

  2. +----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+

  3. | id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra       |

  4. +----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+

  5. | 1  | SIMPLE      | tx    | ref  | idx_type      | idx_type | 1       | const | 6    | Using where |

  6. +----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+

  7. 1 row in set (0.00 sec)

案例二
当查询条件使用了与order by不同的其他的索引,且值为常量,但排序字段是另一个联合索引的非连续部分时
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part1, key_part3;

  1. test [RW] 11:19:17 >desc select * from tx where type=1 order by  gid;

  2. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  3. | id | select_type | table | type | possible_keys | key      | key_len | ref | rows   | Extra                       |

  4. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  5. | 1  | SIMPLE      | tx    | ref  | idx_type      | idx_type | 1       | const | 6    | Using where; Using filesort |

  6. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  7. 1 row in set (0.00 sec)

  8. test [RW] 11:21:08 >desc select * from tx where type=1 order by  shid;

  9. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  10. | id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra                       |

  11. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  12. | 1  | SIMPLE      | tx    | ref  | idx_type      | idx_type | 1       | const | 6    | Using where; Using filesort |

  13. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  14. 1 row in set (0.00 sec)

分析 
  与案例一一致,key2 的顺序语句key1(key_part1)存储排序不一样的情况下,MySQL 都会选择filesort 。
案例三
order by 语句使用了和组合索引默认不同的排序规则
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
官方文档中提示使用混合索引排序规则会导致额外排序,其实我们创建索引的时候可以做 (key_part1 DESC, key_part2 ASC)
案例四
当where 条件中利用的索引与order by 索引不同时,与案例二有相似性。
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

  1. test [RW] 11:19:44 >desc select * from tx where type=1 order by  shid;

  2. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  3. | id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra                       |

  4. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  5. | 1  | SIMPLE      | tx    | ref  | idx_type      | idx_type | 1       | const | 6    | Using where; Using filesort |

  6. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  7. 1 row in set (0.00 sec)

  8. test [RW] 11:20:07 >desc select * from tx where type=1 order by  shid,gid;

  9. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  10. | id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra                       |

  11. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  12. | 1  | SIMPLE      | tx    | ref  | idx_type      | idx_type | 1       | const | 6    | Using where; Using filesort |

  13. +----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------------+

  14. 1 row in set (0.00 sec)

案例五
order by 字段使用了表达式
SELECT * FROM t1 ORDER BY ABS(key);
SELECT * FROM t1 ORDER BY -key;

  1. test [RW] 11:53:39 >desc select * from tx where  shid=3 order  by -shid;

  2. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-----------------------------+

  3. | id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra                       |

  4. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-----------------------------+

  5. | 1  | SIMPLE      | tx    | ref  | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | Using where; Using filesort |

  6. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-----------------------------+

  7. 1 row in set (0.00 sec)

  1. test [RW] 11:56:26 >desc select * from tx where  shid=3 order  by shid;

  2. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------+

  3. | id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra |

  4. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------+

  5. | 1  | SIMPLE      | tx    | ref  | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | NULL |

  6. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------+

分析
    order by 的字段使用函数,和在where条件中使用函数索引一样 ,MySQL都无法利用到索引。
案例六
The query joins many tables, and the columns in the ORDER BY are not all from the first nonconstant table that is used to retrieve rows. (This is the first table in the EXPLAIN output that does not have a const join type.)
当查询语句是多表连接,并且ORDER BY中的列并不是全部来自第1个用于搜索行的非常量表.(这是EXPLAIN输出中的没有使用const联接类型的第1个表)

  1. test [RW] 12:32:43 >explain select shid,gid from tx a left join goods_type b on a.shid=b.id where a.shid=2 order by a.gid,b.id;

  2. +----+-------------+-------+-------+---------------+---------------+---------+-------+------+-------------------------------+

  3. | id | select_type | table | type  | possible_keys | key           | key_len | ref   | rows | Extra                         |

  4. +----+-------------+-------+-------+---------------+---------------+---------+-------+------+-------------------------------+

  5. | 1  | SIMPLE      | a     | ref   | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | Using index; Using temporary;                                                                                                Using filesort                |

  6. | 1  | SIMPLE      | b     | const | PRIMARY       | PRIMARY       | 4       | const | 1    | Using index                   |

  7. +----+-------------+-------+-------+---------------+---------------+---------+-------+------+----------------------------------------------+

  8. 2 rows in set (0.00 sec)

  9. test [RW] 12:32:44 >explain select shid,gid from tx a left join goods_type b on a.shid=b.id where a.shid=2 order by a.gid;

  10. +----+-------------+-------+-------+---------------+---------------+---------+-------+------+--------------------------+

  11. | id | select_type | table | type  | possible_keys | key           | key_len | ref   | rows | Extra |

  12. +----+-------------+-------+-------+---------------+---------------+---------+-------+------+--------------------------+

  13. | 1  | SIMPLE      | a     | ref   | uniq_shid_gid | uniq_shid_gid | 4       | const | 2    | Using where; Using index |

  14. | 1  | SIMPLE      | b     | const | PRIMARY       | PRIMARY       | 4       | const | 1    | Using index |

  15. +----+-------------+-------+-------+---------------+---------------+---------+-------+------+--------------------------+

  16. 2 rows in set (0.00 sec)

分析
  出现join的情况下不能利用索引其实有很多种,只要对a的访问不满足上面说的可以利用索引排序的情况都会导致额外的排序动作。但是当where + order 复合要求,order by 有包含了其他表的列就会导致额外的排序动作。
案例七
sql中包含的order by 列与group by 列不一致 

  1. test [RW] 11:26:54 >desc select * from tx  group by shid order by gid;

  2. +----+-------------+-------+-------+---------------+---------------+---------+------+------+---------------------------------+

  3. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                          |

  4. +----+-------------+-------+-------+---------------+---------------+---------+------+------+--------------------------------+

  5. | 1  | SIMPLE      | tx    | index | uniq_shid_gid | uniq_shid_gid | 8       | NULL | 24   | Using temporary; Using filesor |

  6. +----+-------------+-------+-------+---------------+---------------+---------+------+------+--------------------------------+

  7. 1 row in set (0.00 sec)

group by 本身会进行排序的操作,我们可以显示的注让group by不进行额外的排序动作。

  1. test [RW] 12:09:52 >desc select * from tx  group by shid order by null;

  2. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------+

  3. | id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra |

  4. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------+

  5. | 1  | SIMPLE      | tx    | index | uniq_shid_gid | uniq_shid_gid | 8       | NULL | 24   | NULL |

  6. +----+-------------+-------+-------+---------------+---------------+---------+------+------+-------+

  7. 1 row in set (0.00 sec)

案例八
索引本身不支持排序存储 比如,hash索引。

  1. CREATE TABLE `hash_test` (

  2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT ,

  3.   `name` varchar(20) NOT NULL COMMENT '名称',

  4.   PRIMARY KEY (`id`),

  5.   KEY `name` (`name`)

  6. ) ENGINE=MEMORY ;

  7. INSERT INTO `hash_test` (`id`, `name`) VALUES

  8. (1, '张三'),

  9. (2, '李四');

  10. test [RW] 12:07:27 >explain select * from hash_test force index(name) order by name;

  11. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  12. | id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra          |

  13. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  14. | 1  | SIMPLE      | hash_test | ALL  | NULL          | NULL | NULL    | NULL | 2    | Using filesort |

  15. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  16. 1 row in set (0.00 sec)

  17. test [RW] 12:07:48 >explain select * from hash_test  order by name;

  18. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  19. | id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra          |

  20. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  21. | 1  | SIMPLE      | hash_test | ALL  | NULL          | NULL | NULL    | NULL | 2    | Using filesort |

  22. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  23. 1 row in set (0.00 sec)

  24. test [RW] 12:07:53 >alter table  hash_test ENGINE=innodb;

  25. Query OK, 2 rows affected (0.45 sec)

  26. Records: 2  Duplicates: 0  Warnings: 0

  27. test [RW] 12:08:33 >explain select * from hash_test  order by name;

  28. +----+-------------+-----------+-------+---------------+------+---------+------+------+-------------+

  29. | id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows | Extra |

  30. +----+-------------+-----------+-------+---------------+------+---------+------+------+-------------+

  31. | 1  | SIMPLE      | hash_test | index | NULL          | name | 82      | NULL | 1    | Using index |

  32. +----+-------------+-----------+-------+---------------+------+---------+------+------+-------------+

  33. 1 row in set (0.00 sec)

分析 
   hash 索引本身不支持排序存储,故不能利用到排序特性,将表转化为innodb再次查询,避免了filesort
案例九
order by的索引使用部分字符串 比如 key idx_name(name(2))

  1. test [RW] 12:08:37 >alter table  hash_test  drop key name ,add key idx_name(name(2));

  2. Query OK, 0 rows affected (0.03 sec)

  3. Records: 0  Duplicates: 0  Warnings: 0

  4. test [RW] 12:09:50 >explain select * from hash_test  order by name;

  5. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  6. | id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra          |

  7. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  8. | 1  | SIMPLE      | hash_test | ALL  | NULL          | NULL | NULL    | NULL | 1    | Using filesort |

  9. +----+-------------+-----------+------+---------------+------+---------+------+------+----------------+

  10. 1 row in set (0.00 sec)

三 老生常谈的优化策略
 为了提高order by 查询的速度,尽可能的利用索引的有序性进行排序,如果不能利用索引排序的功能,那么我们只能退而求其次优化order by相关的缓存参数
1 增加 sort_buffer_size 大小,建议sort_buffer_size要足够大能够避免磁盘排序和合并排序次数。
2 增加 read_rnd_buffer_size 大小。
3 使用合适的列大小存储具体的内容,比如对于city字段 varchar(20)比varchar(200)能获取更好的性能。
4 将tmpdir 目录指定到os上面有足够空间的具有比较高iops能力的存储上。

关于如何进行MySQL中的order by 优化就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。


推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 本文介绍了在MySQL8.0中如何查看性能并解析SQL执行顺序。首先介绍了查询性能工具的开启方法,然后详细解析了SQL执行顺序中的每个步骤,包括from、on、join、where、group by、having、select distinct、union、order by和limit。同时还介绍了虚拟表的概念和生成过程。通过本文的解析,读者可以更好地理解MySQL8.0中的性能查看和SQL执行顺序。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
author-avatar
才女与尔同销万古愁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有