MySQL联合索引是不支持不同排序规则解决方案
2016-05-10 00:00
633 查看
摘要: 做了一个简单的网页应用,最初数目比较小的时候没有发现什么问题,觉得索引都做得挺好的。
但是:当数目到达20w左右,并且筛选出的东西越多的时候,发现排序越慢。找了一下原因
先来看一下表结构,这是一张新闻表:
我想查的sql是这样的:
就是根据时间和排序选择出最新,排名最靠前的新闻。经验丰富的DBA估计一看就找出了问题,可是我是菜鸟.....
explian 一把:
看到了吧,using Filesort。可我觉得我的联合索引就是应该这样建啊......
确实是应该这样建,但是,MySQL联合索引是不支持不同排序规则。
原因在于,news_wild_card_index使用的时候一个为DESC一个为ASC,排序顺序不同啊,所以最终用上了filesort。
为了用上索引,所以根据自己的业务调整了一下,主要解决思路就是:让news_time,rank都使用desc排序(这显然不符合我的业务逻辑),但是原先的rank更改为1000-rank.实际效果就和最初的需求一致了。但这个解决方案需要在原有的程序做一定的改变,不过性能确实上去了。
所以在原先的表当中做了这样一个update
当然程序当中也需要做响应的修改。
最终explain的结果:
但是:当数目到达20w左右,并且筛选出的东西越多的时候,发现排序越慢。找了一下原因
先来看一下表结构,这是一张新闻表:
Table: news_news Create Table: CREATE TABLE `news_news` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(128) NOT NULL, `rank` int(11) NOT NULL, `news_time` date NOT NULL, `publisher` varchar(128) NOT NULL, `news_url` varchar(200) NOT NULL, `content` longtext NOT NULL, `hash_digest` varchar(64) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `hash_digest` (`hash_digest`), KEY `news_wild_card_index` (`news_time`,`rank`) ) ENGINE=InnoDB AUTO_INCREMENT=154239 DEFAULT CHARSET=utf8 1 row in set (0.04 sec)
我想查的sql是这样的:
SELECT `news_news`.`id`, `news_news`.`title`, `news_news`.`rank`, `news_news`.`news_time`, `news_news`.`content` FROM `news_news` WHERE (`news_news`.`news_time` >= '2011-09-01' AND `news_news`.`news_time` <= '2016-05-10') ORDER BY `news_news`.`news_time` DESC, `news_news`.`rank` ASC LIMIT 9;
就是根据时间和排序选择出最新,排名最靠前的新闻。经验丰富的DBA估计一看就找出了问题,可是我是菜鸟.....
explian 一把:
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: news_news type: range possible_keys: news_wild_card_index key: news_wild_card_index key_len: 3 ref: NULL rows: 64614 Extra: Using index condition; Using MRR; Using filesort 1 row in set (0.00 sec)
看到了吧,using Filesort。可我觉得我的联合索引就是应该这样建啊......
确实是应该这样建,但是,MySQL联合索引是不支持不同排序规则。
原因在于,news_wild_card_index使用的时候一个为DESC一个为ASC,排序顺序不同啊,所以最终用上了filesort。
为了用上索引,所以根据自己的业务调整了一下,主要解决思路就是:让news_time,rank都使用desc排序(这显然不符合我的业务逻辑),但是原先的rank更改为1000-rank.实际效果就和最初的需求一致了。但这个解决方案需要在原有的程序做一定的改变,不过性能确实上去了。
所以在原先的表当中做了这样一个update
update news_news set rank=1000-rank where id>0;
当然程序当中也需要做响应的修改。
最终explain的结果:
explain SELECT `news_news`.`id`, `news_news`.`title`, `news_news`.`rank`, `news_news`.`news_time`, `news_news`.`content` FROM `news_news` WHERE (`news_news`.`news_time` >= '2011-09-01' AND `news_news`.`news_time` <= '2016-05-10') ORDER BY `news_news`.`news_time` DESC, `news_news`.`rank` DESC LIMIT 9\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: news_news type: range possible_keys: search_result_index key: search_result_index key_len: 3 ref: NULL rows: 45638 Extra: Using index condition 1 row in set (0.01 sec)
相关文章推荐
- 在命令行用 sort 进行排序
- 文件遍历排序函数
- C#选择排序法实例分析
- C#插入法排序算法实例分析
- C#实现Datatable排序的方法
- MYSQL必知必会读书笔记第五章之排序检索数据
- SQLSERVER的排序问题结果不是想要的
- Windows Powershell排序和分组管道结果
- C#通过IComparable实现ListT.sort()排序
- C#选择法排序实例分析
- SQL学习笔记四 聚合函数、排序方法
- C#对list列表进行随机排序的方法
- jQuery拖动元素并对元素进行重新排序
- 将MySQL查询结果按值排序的简要教程
- 一根网线内的8根线哪4根是传输数据的,哪四根是防干扰的
- 在ASP.NET 2.0中操作数据之二十四:分页和排序报表数据
- C语言实现选择排序、冒泡排序和快速排序的代码示例
- C#折半插入排序算法实现方法
- SQL进行排序、分组、统计的10个新技巧分享
- 简单了解C语言中直接插入排序与直接选择排序实现