我有一个数据库,其中用户由哈希表示。每个用户(哈希)都有相关的值(与他正在收听的音乐曲目有关)。由于用户可以收听多个轨道,因此存在用户和相关数据的重复实例(数据不同,因为它现在是不同的轨道)。
我想要做的是从这个数据库中随机选择~10个用户,然后找到他们的相关数据。
目前,我使用的代码是:
SELECT *
FROM `tblPlayLogV4`
WHERE `titleId` <> 0 AND `hash` IN (SELECT `hash` FROM `tblPlayLogV4` WHERE `titleId` <> 0 AND RAND() <= 0.1 GROUP BY `hash` HAVING COUNT(`hash`) > 500);
为什么选择RAND() - 因为内部查询中不允许使用LIMIT。 RAND()的想法在这里 - http://www.rndblog.com/how-to-select-random-rows-in-mysql/
上述查询需要很长时间才能完成。
但是,如果我单独运行内部查询,它将在4.53s完成。然后我在外部查询中硬编码内部查询的结果,并在大约275毫秒内完成。分离的查询如下所示:
SELECT `hash` FROM `tblPlayLogV4` WHERE `titleId` <> 0 AND RAND() <= 0.1 GROUP BY `hash` HAVING COUNT(`hash`) > 500);
SELECT * FROM `tblPlayLogV4` WHERE `hash` IN ('-29e291921cccd06a5813bca17b7f7c3','-2c08232108dcd93c443d821165c2c79','-58285c1602072da713e51cc6cdc6313','-5bcc2c42482d5805277609a84474aef','-79ecab520d661a1d624de7e7b04f265','-e937c753a96fc9e441f83af97b08489','04d3f1e91e4e92970819190346405d2d','3f9f0cd502de38d47e39367cdfdd6722') AND `titleId`<>0;
有人可以向我解释为什么会这样吗?我做错了什么?如果我有更好的方法来制定我的查询,请告诉我。
数据库中的条目数:6,322,605
答案 0 :(得分:1)
不同之处在于第一个查询正在处理所有6,322,605条记录。但第二个查询只处理10.所以是的,第二个查询将是缓慢的。基本上你需要一种方法来选择600万中的10个,而不需要处理所有600万......
“最简单”的替代方案,为每条记录赋予“sequence_id”列,并索引该列。您只需生成10个随机值,然后使用SELECT * FROM table WHERE sequence_id IN (a,b,c,d,etc)
直接提取这些记录。但是,这确实要求您确保sequence_id没有间隙。
那么,您是否曾从该表中删除,或只是附加到它?
如果您 从中删除,您仍然可以通过从表末尾获取记录并使用刚删除的值更新其sequence_id(可能带有触发器)来确保“无间隙” )。这种可行性取决于您从表中删除的频率。
答案 1 :(得分:1)
正如Dems所说,您现有的查询正在子查询中为主查询表中的每条记录执行RAND()选择。
所以尝试重写这样的主要查询:
SELECT f.*
FROM (SELECT `hash`
FROM `tblPlayLogV4`
WHERE `titleId` <> 0 AND RAND() <= 0.1
GROUP BY `hash`
HAVING COUNT(`hash`) > 500) r
JOIN `tblPlayLogV4` f on r.`hash` = f.`hash` and f.`titleId` <> 0;