`
丁林.tb
  • 浏览: 789587 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

MySQL中order by的实现 和 by rand() 和优化

阅读更多

有同学上周问了个问题 “MySQL 里面的order by rand()”是怎么实现的。我们今天来简单说说MySQL里的order by。

 

    几种order by的情况
    乍一看这个问题好像有点复杂,我们从最简单的case开始看起。
    用这个表来说明:(10w行数据)

 

1、  最简单的order ―― order by索引字段

 从explain的结果来看(Extra列),这个语句并不作排序。因为字段a已经是有顺序的。就是按照索引a的顺序依次读pk的值(在这里是隐藏的系统列),一个个从聚簇索引的data中读入。

 

 2、  复杂一点 ―― order by 非索引字段

    这里Extra列显示一个Using filesort。这里的filesort并不是指字面上的“文件排序”,说的就是与上面一种情况相比,在Server层作了排序。至于是否使用文件,取决于排序过程中的内存是否足够,不够则需要临时文件。

 

    并不到此为止,我们细细想一下,server层要怎么作排序呢

    一个简单的想法是把表数据都读到内存,然后排序。读到内存当然可以想怎么整就怎么整。但是这个做法很耗费内存。需要占用与表一样大小的内存。

 

    另外一个做法,只读入字段b和其对应的主键id。可以想象为这两个字段构成的结构体,按照b的值作排序。排序完成后,按字段b的顺序依次取主键id,取得结果返回。

 

    实际上第二种作法就是这个例子中的实际执行过程。存放用于排序的字段值的结构我们称为sort_keys.

至于order by b,c这样的语句,效果与order by b相同,可以简单理解为上面结构体多了一个字段。

 

 3、  字段函数排序

     有了上面的流程,这里就简单了,还是按顺序读入所有的字段b,只是sort_keys中存的是b的长度而已。

 

4、Order by rand()

    按照自然想法, order by rand() 也可以仿照上面描述的做法,对于每一行,将生成的rand()的值放入sort_kyes里即可。但实际上上效果如下:

    Extra字段里面有一个Using temporary, 也就是说用到了临时表。那么Using temporary的时候操作流程是怎样的呢?
    a)   创建一个heap引擎的临时表,字段名为 ”” a b c d, 第一个字段为匿名;
    b)   将表tb中的数据按行读入到临时表中,同时给第一字段填入一个随机实数(0,1);
    c)   按照第一个字段排序,返回
    d)   查询完成删除临时表

    分析一下这个过程,由于把数据从InnoDB表里面读入临时表,则InnoDB表实际上也已经读入内存,在这个过程中,若不考虑内存不够时的写文件策略, 则内存中有两份表的全拷贝;另外多了从内存中将数据一一拷贝到临时表的过程。

 

     这个查询在我的测试环境中耗时2.41s(多次次执行,不计第一次加载数据的时间) 

order by rand()的改进
    我们前面说过,实际上对于这种简单的order by rand() 的情况,也可以等同于按照非索引字段来处理。在sort_array 中存入随机值即可。
     按照这个思路的patch在这里,效果上

 
    执行时间减少为1.89s,性能提升21%, 这个例子单行1k,单行越大提升效果越好。

3
0
分享到:
评论
2 楼 wtwei 2012-07-31  
你好,我想请教一个问题关于FIND_IN_SET的性能问题,我想在项目中存储分级记录的ID(省,市,区)这样在查询的时候就可以一次得到关联的ID,在查询的时候我使用了FIND_IN_SET来匹配某一个省或市或区 的ID,我查过一些资料说FIND_IN_SET比like的性能高,可不知道FIND_IN_SET对10w+数量级的查询会不会有性能问题?希望指教,谢谢
1 楼 babaoqi 2012-07-27  
学习力

相关推荐

    MySQL Order By Rand()效率分析

    最近由于需要大概研究了一下...但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机。 但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上。查看官方手册,也说rand

    MySQL优化之对RAND()的优化方法

    众所周知,在MySQL中,如果直接 ORDER BY RAND() 的话,效率非常差,因为会多次执行。事实上,如果等值查询也是用 RAND() 的话也如此,我们先来看看下面这几个SQL的不同执行计划和执行耗时。 首先,看下建表DDL,这...

    MYSQL随机抽取查询 MySQL Order By Rand()效率问题

    MYSQL随机抽取查询:MySQL Order By Rand()效率问题一直是开发人员的常见问题,俺们不是DBA,没有那么牛B,所只能慢慢研究咯,最近由于项目问题,需要大概研究了一下MYSQL的随机抽取实现方法

    mysql中RAND()随便查询记录效率问题和解决办法分享

    举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。 有两个方法可以达成以上效果. 1.新建一个表,里面存着 -5 至 5 之间的数.再利用order by ...

    MySQL下的RAND()优化案例分析

    众所周知,在MySQL中,如果直接 ORDER BY RAND() 的话,效率非常差,因为会多次执行。事实上,如果等值查询也是用 RAND() 的话也如此,我们先来看看下面这几个SQL的不同执行计划和执行耗时。 首先,看下建表DDL,这...

    MySQL rand函数实现随机数的方法

    顺便给你找了点关于mysql rand函数的实例,如下:那就在insert 命令中,value()里面用rand(),注意字段宽度是否够一直以为mysql随机查询几条数据,就用SELECT * FROM `table` ORDER BY RAND() LIMIT 5 就可以了。

    mysql优化取随机数据慢的方法

    前天因为工作需要我把从一个5W记录的数据库中随机抽取几条记录了,这里我是直接使用mysql rand by函数来直接,几千条记录没关系,但如果到了几万条感觉要几秒,这个就很慢了,下面小编与大家一起来看看mysql 取随机...

    MySQL性能优化的21个最佳实践.pdf

    1. 为查询缓存优化你的查询 2. EXPLAIN 你的 SELECT 查询 ...6. 千万不要 ORDER BY RAND() 7. 避免 SELECT * 8. 永远为每张表设置一个 ID 9. 使用 ENUM 而不是 VARCHAR 10. 从 PROCEDURE ANALYSE() 取得建议 ......等等

    MYSQL 随机 抽取实现方法及效率分析

    但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机。 但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上。查看官方手册,也说rand()放在ORDER BY 子句中会被执行...

    MySQL查询随机数据的4种方法和性能对比

    方案一: 代码如下:SELECT * FROM `table` ORDER BY RAND() LIMIT 0,1;这种方法的问题就是非常慢。原因是因为MySQL会创建一张零时表来保存所有的结果集,然后给每个结果一个随机索引,然后再排序并返回。有几个方法...

    MySQL 随机函数获取数据速度和效率分析

    在mysql中带了随机取数据的函数,在mysql中我们会有rand()函数,很多朋友都会直接使用,如果几百条数据肯定没事,如果几万或百万时你会发现,直接使用是错误的。下面我来介绍随机取数据一些优化方法。 SELECT * FROM...

    数据库查询排序使用随机排序结果示例(Oracle/MySQL/MS SQL Server)

    MySQL随机查询出一条记录: 代码如下: — 下面的查询语句效率高,不要使用 SELECT * FROM table1 ORDER BY rand() LIMIT 1 来查询 SELECT * FROM table1 WHERE id=(SELECT id FROM table1 ORDER BY rand() LIMIT 1)...

    MySQL 随机查询数据与随机更新数据实现代码

    MySQL随机查询数据 以前在群里讨论过这个问题,比较的有意思.MySQLl的语法真好玩.他们原来都想用PHP的实现随机,但取出多条好像... 关于MySQL的rand()函数的效率问题,大家可以参考《MySQLL Order By Rand()效率》:http:

    从MySQL数据库表中取出随机数据的代码

    SELECT * FROM table_name ORDER BY rand() LIMIT 5; rand在手册里是这么说的: RAND()  RAND(N)  返回在范围0到1.0内的随机浮点值。如果一个整数参数N被指定,它被用作种子值。  mysql> select RAND...

    MySQL取出随机数据

    SELECT * FROM table_name ORDER BY rand() LIMIT 5; rand在手册里是这么说的: RAND()  RAND(N)  返回在范围0到1.0内的随机浮点值。如果一个整数参数N被指定,它被用作种子值。  mysql> select RAND...

    MySql基本查询、连接查询、子查询、正则表达查询讲解

    查询数据是指从数据库中的数据表或视图中获取所需要的数据,在mysql中,可以使用SELECT语句来查询数据。根据查询条件的不同,数据库系统会找到不同的数据。 SELECT语句的基本语法格式如下: [sql] view plain copy ...

    Java面试准备:数据库MySQL性能优化

    为查询缓存优化你的查询 EXPLAIN你的SELECT查询 当只要一行数据是使用LIMIT 1 为搜索字段建索引 在Join表的时候使用相当类型的列,并将其索引 千万不要ORDER BY RAND() 避免SELECT * 永远为每张表设置一个ID 使用...

Global site tag (gtag.js) - Google Analytics