求指教带where条件的mysql随机查询n条记录的高效方法

terry_sdy 2016-08-24 03:27:37
搜索了mysql随机查询,都是没有带where条件的,直接硬套的话limit获取到的记录个数不确定就需要一个while循环知道获取到需要的记录数,加了while循环的效率当然是很低很低的。也试了从数据库直接拿所有满足where条件的记录,再在java里面随机拿若干个,这也肯定是不合理的,效率跟记录总数有关跟所需记录无关,效率也非常低。求大神指教解决方法
...全文
1978 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
小灰狼 2016-08-26
  • 打赏
  • 举报
回复
select * from ..... where id in (3,6,8,23,4); id 列表是随机数,由 Java 随机生成 当然,如果表中数据的Id不连续,那么查出来的结果肯定不足
hdcopy2001 2016-08-26
  • 打赏
  • 举报
回复
引用 27 楼 terry_sdy 的回复:
啊啊啊啊啊啊 好尴尬呀,之前说的很慢的几种方法都是因为没有把日志等级调好,控制台在疯狂输出日志造成的时间浪费啊 谢谢大家啦
别走!把分留下
terry_sdy 2016-08-26
  • 打赏
  • 举报
回复
啊啊啊啊啊啊 好尴尬呀,之前说的很慢的几种方法都是因为没有把日志等级调好,控制台在疯狂输出日志造成的时间浪费啊 谢谢大家啦
hdcopy2001 2016-08-25
  • 打赏
  • 举报
回复
用这样只返回主键的SQL做子查询,再复杂表又怎样,开销还是在条件查询上。
hdcopy2001 2016-08-25
  • 打赏
  • 举报
回复
按条件取出10w条记录,再从10W中随机取100条,花费都在前面取10W条记录上呢。
hdcopy2001 2016-08-25
  • 打赏
  • 举报
回复
测试表,仅主键
CREATE TABLE `test` (
  `sss` varchar(20) NOT NULL,
  PRIMARY KEY (`sss`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
生成100W数据
CREATE  PROCEDURE `aa`()
BEGIN
	DECLARE i int;
	DECLARE c int;
	set i = 0;
  set autocommit = 0;
	while i < 1000 do
		set c = 0;
		while c < 1000 do
			insert into test VALUES( LPAD(i*1000+c,10,'0'));
			set c=c+1;
		end while;
		commit;
	  set i=i+1;
	end while;
  set autocommit = 1;
END
查询
select * from test WHERE sss > '0000100023' and sss < '0000200023'  ORDER BY rand() LIMIT 100
耗时0.12S, 服务器是阿里云RDS最低配置。 ORDER BY rand() LIMIT N会慢吗?
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 21 楼 ACMAIN_CHM 的回复:
先看 where 后符合条件的有多少条,然后再讨论。
真实条件下应该是只需要在符合where条件的记录里面随机取一小部分的。可能几千条取十几条甚至几万去十几条吧。甲方目前还没给具体的数据,但是我们估计大概这个量。
ACMAIN_CHM 2016-08-24
  • 打赏
  • 举报
回复
先看 where 后符合条件的有多少条,然后再讨论。
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 19 楼 qinyanbin123 的回复:
哦哦 哈哈 我感觉sql实现不了 用java取随机那样就行了 我随机过上百万的数据 数据大 有点慢 没法 有兴趣 加下群吧 可以交流 79124001 扯淡 聊技术
好呀~
  • 打赏
  • 举报
回复
哦哦 哈哈 我感觉sql实现不了 用java取随机那样就行了 我随机过上百万的数据 数据大 有点慢 没法 有兴趣 加下群吧 可以交流 79124001 扯淡 聊技术
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 17 楼 qinyanbin123 的回复:
你查询不是一分钟就行了 查询list集合 然后用java随机 这个就可以了啊 你写一个逻辑业务 你要控制多长时间呢?这个是说不准的
这也是我目前试的几种里面最快的啦,不知道还有没有更快的方法,所以来求指教一下嘛~
  • 打赏
  • 举报
回复
你查询不是一分钟就行了 查询list集合 然后用java随机 这个就可以了啊 你写一个逻辑业务 你要控制多长时间呢?这个是说不准的
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 14 楼 qinyanbin123 的回复:
[quote=引用 13 楼 terry_sdy 的回复:] [quote=引用 10 楼 qinyanbin123 的回复:] SELECT * FROM table WHERE id >= ( (SELECT MAX(id) FROM table WHERE xxx = 'xxx')- (SELECT MIN(id) FROM table WHERE xxx= 'xxx') ) * RAND() + (SELECT MIN(id) FROM table WHERE xxx= 'xxx') LIMIT n 你试试这样行不 利用id取 n是要取得条数
嗯啊,这样查询的速度确实很快的。但是我题目里面说的while循环就是这种情况,那个单元测试用的sql就是这种随机取的方法,这样的limit n如果加了where条件,取到的就不一定是n,所以我加了个while循环知道取到n个才走下一步。加了while循环为了确保获取n个,循环六次从70多条记录里面总共取十多条记录的单元测试,就让我看着控制台发呆好久啦,有时候一分多钟可以跑完,有时候三分钟都没跑完,while循环太恐怖啦[/quote] 那你就别用sql了 java处理吧 像你说的拿到所有where条件的数据,放list中 然后随机取N条 从list中去随机取 给你一段 list中随机取多少的代码 你看看 /** * 函 数 名 :getRandomNumList * 方法描述:随机抽取N个元素 * @param list 总数量 * @param selected 取多少元素 * @return List<String> */ public List<bean> getRandomNumList(List<bean> list, int selected) { List<beanVo> reList = new ArrayList<beanVo>(); Random random = new Random(); for (int i = 0; i < selected; i++) { // 随机数的范围为0-list.size()-1; int target = random.nextInt(list.size()); reList.add(list.get(target)); } return reList; }[/quote] 刚才回错啦,跑了好几分钟的写法是 SELECT * FROM table WHERE xxx='xxx' AND id >= ( (SELECT MAX(id) )- (SELECT MIN(id) FROM table ) ) * RAND() + (SELECT MIN(id) ) LIMIT n 取所有再java随机取的方法可以实现啦,但是将近一分钟也还是有点难以忍受啦。
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 12 楼 qinyanbin123 的回复:
SELECT * FROM table WHERE id >= ( (SELECT MAX(id) FROM table WHERE xxx = 'xxx')- (SELECT MIN(id) FROM table WHERE xxx= 'xxx') ) * RAND() + (SELECT MIN(id) FROM table WHERE xxx= 'xxx') LIMIT n 满足where条件的随机数 取n条数据 试试楼主
这样查出来的不一定都满足where条件的吧? 查出的是满足where条件的最小id到最大id之间的随机n个,但是这之间并不是全都满足where条件的吧?
  • 打赏
  • 举报
回复
引用 13 楼 terry_sdy 的回复:
[quote=引用 10 楼 qinyanbin123 的回复:] SELECT * FROM table WHERE id >= ( (SELECT MAX(id) FROM table WHERE xxx = 'xxx')- (SELECT MIN(id) FROM table WHERE xxx= 'xxx') ) * RAND() + (SELECT MIN(id) FROM table WHERE xxx= 'xxx') LIMIT n 你试试这样行不 利用id取 n是要取得条数
嗯啊,这样查询的速度确实很快的。但是我题目里面说的while循环就是这种情况,那个单元测试用的sql就是这种随机取的方法,这样的limit n如果加了where条件,取到的就不一定是n,所以我加了个while循环知道取到n个才走下一步。加了while循环为了确保获取n个,循环六次从70多条记录里面总共取十多条记录的单元测试,就让我看着控制台发呆好久啦,有时候一分多钟可以跑完,有时候三分钟都没跑完,while循环太恐怖啦[/quote] 那你就别用sql了 java处理吧 像你说的拿到所有where条件的数据,放list中 然后随机取N条 从list中去随机取 给你一段 list中随机取多少的代码 你看看 /** * 函 数 名 :getRandomNumList * 方法描述:随机抽取N个元素 * @param list 总数量 * @param selected 取多少元素 * @return List<String> */ public List<bean> getRandomNumList(List<bean> list, int selected) { List<beanVo> reList = new ArrayList<beanVo>(); Random random = new Random(); for (int i = 0; i < selected; i++) { // 随机数的范围为0-list.size()-1; int target = random.nextInt(list.size()); reList.add(list.get(target)); } return reList; }
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 10 楼 qinyanbin123 的回复:
SELECT * FROM table WHERE id >= ( (SELECT MAX(id) FROM table WHERE xxx = 'xxx')- (SELECT MIN(id) FROM table WHERE xxx= 'xxx') ) * RAND() + (SELECT MIN(id) FROM table WHERE xxx= 'xxx') LIMIT n 你试试这样行不 利用id取 n是要取得条数
嗯啊,这样查询的速度确实很快的。但是我题目里面说的while循环就是这种情况,那个单元测试用的sql就是这种随机取的方法,这样的limit n如果加了where条件,取到的就不一定是n,所以我加了个while循环知道取到n个才走下一步。加了while循环为了确保获取n个,循环六次从70多条记录里面总共取十多条记录的单元测试,就让我看着控制台发呆好久啦,有时候一分多钟可以跑完,有时候三分钟都没跑完,while循环太恐怖啦
  • 打赏
  • 举报
回复
SELECT * FROM table WHERE id >= ( (SELECT MAX(id) FROM table WHERE xxx = 'xxx')- (SELECT MIN(id) FROM table WHERE xxx= 'xxx') ) * RAND() + (SELECT MIN(id) FROM table WHERE xxx= 'xxx') LIMIT n 满足where条件的随机数 取n条数据 试试楼主
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 9 楼 terry_sdy 的回复:
[quote=引用 5 楼 hdcopy2001 的回复:] 度娘的回答是加 ORDER BY rand() LIMIT n , 没毛病啊,为啥不接受
引用 8 楼 hongyawang 的回复:
select * from table order by rand() limit n n为随机取条数,效率数据量大低。可以自己生成随机数取。
随便写了个 循环6次的从100个查15个的单元测试,跑了五分钟还没有出结果啦[/quote] 取全部满足where条件的记录,再在java里面随机取若干个,这样从循环六次从一万取150个的单元测试用了将近一分钟,一分钟就已经不能忍受啦
  • 打赏
  • 举报
回复
SELECT * FROM table WHERE id >= ( (SELECT MAX(id) FROM table WHERE xxx = 'xxx')- (SELECT MIN(id) FROM table WHERE xxx= 'xxx') ) * RAND() + (SELECT MIN(id) FROM table WHERE xxx= 'xxx') LIMIT n 你试试这样行不 利用id取 n是要取得条数
terry_sdy 2016-08-24
  • 打赏
  • 举报
回复
引用 5 楼 hdcopy2001 的回复:
度娘的回答是加 ORDER BY rand() LIMIT n , 没毛病啊,为啥不接受
引用 8 楼 hongyawang 的回复:
select * from table order by rand() limit n n为随机取条数,效率数据量大低。可以自己生成随机数取。
随便写了个 循环6次的从100个查15个的单元测试,跑了五分钟还没有出结果啦
加载更多回复(8)

56,677

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧