我一直没有问,因为我觉得这个问题被问了这么多,但仍然缺乏明确的答案:
对象表:40M+ 行,以 UPC、EIN、ISBN 作为 obj_id 主键填充。差距
*Obj_Cat* 表:将对象链接到类别。|的列 obj_id | cat_id |
问题:返回 5 个非顺序随机 obj_id 的最佳方法是什么?有没有比我列出的更好的方法?
解决方案1: SELECT objects.obj_id FROM objects left join obj_cat on objects.obj_id=obj_cat.obj_id WHERE obj_cat.cat_id=cat_id ORDER BY RAND() LIMIT 1;
运行5次
- 大桌子很慢。
解决方案2: SELECT obj_id FROM objects WHERE obj_id >= (SELECT FLOOR( MAX(obj_id) * RAND()) FROM
objects) LIMIT 1;
运行5次(不包括obj_cat join,让它更容易理解)
如果您的行没有间隙或间隙可忽略不计,则为最佳解决方案。非常快。
不适用于类别,因为编号不可避免地会出现空白。
解决方案3: SELECT FLOOR(RAND() * COUNT(objects.*)) AS
偏移FROM objects, obj_cat WHERE objects.obj_id=obj_cat.obj_id AND obj_cat.cat_id=cat_id; SELECT obj_id FROM objects LIMIT $offset, 1
运行5次
- 非常灵活。比解决方案 1 快得多。适用于间隙。但在 40M+ 行时,单个 'LIMIT $offset, 1' 仍可能需要 1 分钟。
我使用了解决方案 3,但速度很慢。我目前的解决方案是移动使用 Solr randomsortfield,因为在 fq 中指定我的类别很容易。
索尔解决方案: ?q=*&fl=obj_id&fq=cat:(cat_id)&sort=random_* desc&rows=5
- 相当快,每个类别大约需要 45 秒,但会在运行中返回 5 个非顺序结果。
人们在处理大型数据集时是否发现了更好的方法?我知道这似乎是一个重复的问题,但我想我会用 40M+ 表贡献我的经验。