
ORDER BY rand()速度太慢,主键又不连续(类似于 1,6,7,33,78,93 这种递增),要不然都可以用 php 生成 30 个随机数 id 去 query 了
1 huabalance 2021 年 2 月 19 日 via Android 不断 rand 直到取慢三十个 可能还要去重 |
2 huabalance 2021 年 2 月 19 日 via Android 我是说 php 生成随机数。。。 |
3 0TSH60F7J2rVkg8t 2021 年 2 月 19 日 随机生成 30 个数字,WHERE ID >= 你的某个随机数字 LIMIT 1,执行 30 次查询,这样呢? |
4 honeycomb 2021 年 2 月 19 日 via Android 另外建一个索引表,从那个表里取随机值? |
6 caola 2021 年 2 月 19 日 ``` SELECT * FROM XXX WHERE id >= ((SELECT MAX(id) FROM XXX)-(SELECT MIN(id) FROM XXX)) * RAND() + (SELECT MIN(id) FROM XXX) limit 30; ``` 在网上抄来的 |
8 Duolingo 2021 年 2 月 19 日 via Android 我觉得只要 sql 里有 rand 就会慢。 还是维护个 set,保存生成的随机数,然后生成满 30 个随机数每次取一个最快。 |
9 bthulu 2021 年 2 月 19 日 每次随机三十个数, 数字间大小至少相差十万万, 比如[5001, 235555, 1053052, ...], 然后查询 id>5001 limit 1 union id>23555 limit1 union id>1053052 limit1 ... |
10 dafsic 2021 年 2 月 19 日 随机生成 100 个数,然后 query,结果中大概率会有 30 个 |
11 caola 2021 年 2 月 19 日 @Rocketer #7 如果一定要很随机的话,可以把所有的 ID 保存到 redis 并维护这个 ID 列表, 然后 srandmember 命令去取 |
13 siweipancc 2021 年 2 月 19 日 via iPhone 不上 redis 还有个折衷的方法,额外生成一列 hash,生成索引,取 30 行列值>=随机生成的 hash 的就行了 |
14 shyling 2021 年 2 月 19 日 增加一个存随机数的列 a 加 index,查询的时候再生成个随机数 b,找 a 在 b 附近的 30 条 |
15 Amayadream 2021 年 2 月 19 日 一般这种不符合常理的需求都不是原始需求,可以说一下你的原始需求是什么。 |
16 aeli 2021 年 2 月 19 日 取最大最小 id,然后计算出差值,再在这个差值中,取 60 个随机数后排序,select * from id in( ( a1> and < a2 )or( a3 > < a4) ....)... 大概的思路吧,取两个值之间的一个。 |
17 lovecy 2021 年 2 月 19 日 假设只有 100 条数据 ```sql SELECT * FROM (SELECT * FROM xxx WHERE id > FLOOR(RAND()*100) LIMIT 1) AS n1 UNION SELECT * FROM (SELECT * FROM xxx WHERE id > FLOOR(RAND()*100) LIMIT 1) AS n2 UNION SELECT * FROM (SELECT * FROM xxx WHERE id > FLOOR(RAND()*100) LIMIT 1) AS n3 #写 30 遍,查出来有重复的再查一次 ``` FLOOR(RAND()*100),这一步可以先在代码里算出来,整个方法前提是要知道 id 的最大范围 |
18 laminux29 2021 年 2 月 19 日 这种问题明显应该用空间去换时间,比如在数据录入时,就概率性地取出某些行,直接作为最终数据。 |
19 xxxyh 2021 年 2 月 19 日 order by rand 全表扫描,还排序,如果对随机性要求不是很高的话,可以在取最大和最小 id,在应用层随机取 30 个 id,然后 select * from table where id > (随机出来的 id) limit 1,重复 30 次 |
20 xxxyh 2021 年 2 月 19 日 如果一定要非常精确的随机的话,可以 select count(*) from table,然后在应用层随机出来 30 个 id,把这 30 个 id 排序,从最小的 id@1 开始,select * from table limit id@1,1,从第二条开始 select * from table limit (id@2 - id@1),1 |
21 xxxyh 2021 年 2 月 19 日 如果一定要非常精确的随机的话,可以 select count(*) from table,然后在应用层随机出来 30 个 id,把这 30 个 id 排序,从最小的 id@1 开始,select * from table limit id@1,1,从第二条开始 select * from table where id > (第一次取出来的 id) limit (id@2 - id@1),1 |
22 eastphoton 2021 年 2 月 19 日 既然主键 ID 没有更多规律,总得查一下或者干脆拿到所有 ID 才能得知具体某个 ID 存不存在这个信息了。。 所有 ID 单独维护一份感觉比较合适,上 redis 或者自己维护个 set 。 要么就用一些不那么随机的方案。 |
23 hannibalm 2021 年 2 月 19 日 再建一个临时表,一列现有主键,一列从 1 开始的序号。然后随机抽 30 个。 |
25 bertonzh 2021 年 2 月 19 日 先加一个自增字段进去... |
26 zlowly 2021 年 2 月 19 日 mariadb.com 的 Knowledge Base 知识库上有一篇专门讲这个问题的文章,里面提到一些较快但没那么随机的方法,你可以搜索来参考下 data-sampling-techniques-for-efficiently-finding-a-random-row |
27 stevenkang 2021 年 2 月 19 日 数据库不是用来存取数据的吗,用来做这些复杂的活干嘛。 直接程序随机生成 ID 呗,如 #3 所说取满 30 个就行了。 |
28 yixiugegegege 2021 年 2 月 19 日 |
29 Still4 2021 年 2 月 19 日 我觉得直接说业务吧,啥需求要一亿行里面去随机啊,上面说加自增字段也好,加表也好都是空间换时间,根源上如果需求可以变通的话根本就不需要这么做 |
30 ivanMeng 2021 年 2 月 19 日 布隆过滤器吧,可以快速判断 key 是否存在,id 乱序的 mysql 聚族索引也没发挥出,又是随机的记录地址完全不相邻,更加缓慢,还有这问题本身就是问题 。1 亿的表 是否有读写分离?上层是否有缓存冷热数据分离? |
31 mosliu 2021 年 2 月 19 日 看你的数据 id 有多稀疏 不是太稀疏的话 先获取 3*稀疏倍数*2 个随机数 记为 idlist1 然后按 id in idlist1 limit 30 取 架设取出 n 个 然后不够的 再按缺少数量 取随机数 rand 循环( 30-n )次 {取 id>rand and not in (已取) limit 1} |
32 akira 2021 年 2 月 19 日 同意 25 楼的, 加个连续的自增字段,立马简单起来了 |
33 love2020 2021 年 2 月 19 日 众所周知,随机数是一个难点 |
35 xcstream 2021 年 2 月 19 日 最快当然不用 mysql 直接写程序用偏移量读取数据文件 |
36 ipwx 2021 年 2 月 19 日 说实话,如果原始 id 不是均匀分布的,那么 id >= RAND() 这种操作去取数字,得出来的结果也不是均匀分布的。 很简单,举个例子:原始 id 是 1, 5, 6, 7 。那么用 id >= min(id) + rand() * (max(id) - min(id)) limit 1 取数字,每个数字被选取的概率为: 1 = 4/7 5 = 1/7 6 = 1/7 7 = 1/7 |
37 ipwx 2021 年 2 月 19 日 生成第二列连续的 id 然后去取,就不会产生这种不均匀分布的问题了。 |
38 ipwx 2021 年 2 月 19 日 1 亿 id 的 int 数组在内存中也就几个 gb 的事情。说实话,单独维护一个索引文件大概都容易搞得定。 |
39 stevefan1999 2021 年 2 月 19 日 你要先定什是 譬如我可以定 generateRandomNumber() { return 4 } 然後按照 random number 做 seed 一 LNG 然後生成一次序... 因不代表不能重啊 不如果要去重那更加要命了 |
40 xumng123 2021 年 2 月 19 日 via iPhone 将 id 放在一个数组里,随机取 39 个后,然后去查一下数据库。 |
42 renmu123 2021 年 2 月 19 日 via Android 搞点伪随机,数据量大了之后,谁也不知道你是真随机还是假随机了 |
&nbp; 44 ckdxc 2021 年 2 月 20 日 随机行号,行不? 感觉不需要随机 id, round(count), 30 个行号必命中 |
45 wakzz 2021 年 2 月 20 日 先看看业务,是不是必须要真随机。有很多业务实际上压根不需要真随机,搞个差一点的伪随机就够用了 |