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

最近由于需要大概研究了一下MYSQL的随机抽取实现方法。举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。
有两个方法可以达成以上效果.
1.新建一个表,里面存着 -5 至 5 之间的数.再利用order by rand()得到随机数.
#建立指定范围数据表


代码如下:

#auther: 小强(占卜师)
#date: 2008-03-31
create table randnumber
select -1 as number
union
select -2
union
select -3
union
select -4
union
select -5
union
select 0
union
select 1
union
select 2
union
select 3
union
select 4
union
select 5

#得到随机数
#auther: 小强(占卜师)
#date: 2008-03-31
select number
from randnumber order by rand() limit 1

优点: 随机数可以指定某部分数据,并不需要连续的.
缺点: 当随机数范围很广的时候,建表比较困难.
2.利用MySQL的ROUND()加上RAND()函数实现
#一句sql语句搞定
#auther: 小强(占卜师)
#date: 2008-03-31


代码如下:

SELECT ROUND((0.5-RAND())*2*5)
#注释
#0.5-rand()可以得到-0.5 至 +0.5的随机数
#(0.5-rand())*2可以得到-1 至 +1的随机数
#(0.5-rand())*2*5可以得到-5 至 +5的随机数
#ROUND((0.5-RAND())*2*5)可以得到-5 至 +5的随机整数

但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机。
但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上。查看官方手册,也说rand()放在ORDER BY 子句中会被执行多次,自然效率及很低。

搜索Google,网上基本上都是查询max(id) * rand()来随机获取数据。


代码如下:

SELECT * FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2 WHERE t1.id >= t2.id ORDER BY t1.id ASC LIMIT 5;

但是这样会产生连续的5条记录。解决办法只能是每次查询一条,查询5次。即便如此也值得,因为15万条的表,查询只需要0.01秒不到。
下面的语句采用的是JOIN,mysql的论坛上有人使用


代码如下:

SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;

我测试了一下,需要0.5秒,速度也不错,但是跟上面的语句还是有很大差距。总觉有什么地方不正常。
于是我把语句改写了一下。


代码如下:

SELECT * FROM `table`
WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`)))
ORDER BY id LIMIT 1;

这下,效率又提高了,查询时间只有0.01秒
最后,再把语句完善一下,加上MIN(id)的判断。我在最开始测试的时候,就是因为没有加上MIN(id)的判断,结果有一半的时间总是查询到表中的前面几行。
完整查询语句是:


代码如下:

SELECT * FROM `table`
WHERE id >= (SELECT floor( RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM `table`)))
ORDER BY id LIMIT 1;
SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id LIMIT 1;

最后在php中对这两个语句进行分别查询10次,
前者花费时间 0.147433 秒
后者花费时间 0.015130 秒
看来采用JOIN的语法比直接在WHERE中使用函数效率还要高很多。
经过多次测试我们得出的结果是利用join的语法比在where中的直接使用要快速不少啊,有更好提交的朋友可以出来讨人聊聊。

(0)

相关推荐

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

    要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1. 但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描.但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机. 但是真正测试一下才发现这样效率非常低.一个15万余条的库,查询5条数据,居然要8秒

  • Mysql带And关键字的多条件查询语句

    MySQL带AND关键字的多条件查询,MySQL中,使用AND关键字,可以连接两个或者多个查询条件,只有满足所有条件的记录,才会被返回. SELECT * | {字段名1,字段名2,--} FROM 表名 WHERE 条件表达式1 AND 条件表达式2 [-- AND 条件表达式n]; 查询student表中,id字段值小于16,并且,gender字段值为nv的学生姓名 可以看出,查询条件必须都满足,才会返回 查询student表中,id字段值在12.13.14.15之中,name字段值以字符串

  • MySQL中使用case when 语句实现多条件查询的方法

    举例如下: 数据表为DemoTable,字段有id, condition1,condition2,condition3,condition4,condition5 要求是查询DemoTable中,condition1,condition2,condition3,condition4,condition5五个字段中符合任意两个或两个以上的条件的内容. 可使用case when来实现这个条件,需要嵌套子查询语句 sql语句代码示例如下: 复制代码 代码如下: SELECT * FROM DemoTa

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

    最近由于需要大概研究了一下MYSQL的随机抽取实现方法.举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1. 有两个方法可以达成以上效果. 1.新建一个表,里面存着 -5 至 5 之间的数.再利用order by rand()得到随机数. #建立指定范围数据表 复制代码 代码如下: #auther: 小强(占卜师) #date: 2008-03-31 create table r

  • MySQL中Multiple primary key defined报错的解决办法

    创建主键可以有两种方式: create table 表名( 字段名 类型, 字段名 类型, -- primary key(name) ); 或者是 create table 表名( 字段名 类型 primary key, 字段名 类型, -- ); 但是要注意的是,想要创建复合主键,就不可以用第二种方式. 下面列举一个小例子: 这里报错Multiple primary key defined,表示定义了多个主键,正确的写法是如下: 如果项设置复合主键,复合主键的特点是同时创建.同时删除,所以需要

  • MySql中使用正则表达式查询的方法

    正则表达式常用来检索和替换那些符合魔种模式的文本.例如从一个文本文件中提取电话号码,查找一篇文章中重复的单词或者替换用户输入的某些敏感词汇等.Mysql 使用 REGEXP 关键字指定正则表达式的字符匹配模式. 1. 字符 '^' 查询以特定字符或字符串开头的记录 SELECT * FROM user WHERE email REGEXP '^a' 字符 '^' 匹配以特定字符或字符串开头的记录,以上语句查询邮箱以 a 开头的记录 2. 字符 ' 查询以特定字符或字符串结尾的记录 SELECT

  • mysql中like % %模糊查询的实现

    1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] WHERE u_name LIKE '%三%' 将会把u_name为"张三","张猫三"."三脚猫","唐三藏"等等有"三"的记录全找出来. 另外,如果需要找出u_name中既有"三"又有"猫"的记录,请使用a

  • MySQL中Like模糊查询速度太慢该如何进行优化

    目录 一.前言: 二.第一个思路建索引 三.INSTR 附:Like是否使用索引? 总结 一.前言: 我建了一个<学生管理系统>,其中有一张学生表和四张表(小组表,班级表,标签表,城市表)进行联合的模糊查询,效率非常的低,就想了一下如何提高like模糊查询效率问题 注:看本篇博客之前请查看:Mysql中如何查看Sql语句的执行时间 二.第一个思路建索引 1.like %keyword 索引失效,使用全表扫描. 2.like keyword% 索引有效. 3.like %keyword% 索引失

  • MySQL中 and or 查询的优先级分析

    这个可能是容易被忽略的问题,首选我们要清楚: MySQL中,AND的执行优先级高于OR.也就是说,在没有小括号()的限制下,总是优先执行AND语句,再执行OR语句. 比如: select * from table where  条件1 AND 条件2 OR 条件3 等价于 select * from table where  ( 条件1 AND 条件2 )  OR 条件3 select * from table where  条件1 AND  条件2 OR 条件3 AND 条件4 等价于 sel

  • 深入了解MySQL中的慢查询

    目录 一.什么是慢查询 二.慢查询的危害 三.慢查询常见场景 总结 一.什么是慢查询 什么是MySQL慢查询呢?其实就是查询的SQL语句耗费较长的时间. 具体耗费多久算慢查询呢?这其实因人而异,有些公司慢查询的阈值是100ms,有些的阈值可能是500ms,即查询的时间超过这个阈值即视为慢查询. 正常情况下,MySQL是不会自动开启慢查询的,且如果开启的话默认阈值是10秒 # slow_query_log 表示是否开启 mysql> show global variables like '%slo

  • 浅谈MYSQL中树形结构表3种设计优劣分析与分享

    目录 简介 问题 设计1:邻接表 表设计 SQL示例 设计2:路径枚举 表设计 SQL示例 设计3:闭包表 表设计 SQL示例 结合使用 表设计 总结 简介 在开发中经常遇到树形结构的场景,本文将以部门表为例对比几种设计的优缺点: 问题 需求背景:根据部门检索人员, 问题:选择一个顶级部门情况下,跨级展示当前部门以及子部门下的所有人员,表怎么设计更合理 ? 递归吗 ?递归可以解决,但是势必消耗性能 设计1:邻接表 注:(常见父Id设计) 表设计 CREATE TABLE `dept_info01

  • MySQL中列转行和行转列总结解决思路

    目录 引言 列转行 行转列 总结 引言 在学习sql中遇到了列转行和行转列的题目,这里总结一下如何在对应的情景下解决不同的题目: 列转行 创建一个表stu_score_01: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for stu_score_01 -- ---------------------------- DROP TABLE IF E

  • MySQL中Union子句不支持order by的解决方法

    本文实例讲述了MySQL中Union子句不支持order by的解决方法.分享给大家供大家参考,具体如下: 我对DB知之甚少,这问题只在MySQL遇到,不知道别的DBMS是不是也如此. 问题是这样的,我打算在一个表里获得与某一行记录相邻的两行,并且想通过union一起取出来,所以这么写: select id,title from subjects where id>#some_id# order by id limit 1 union select id,title from subjects

随机推荐