我试图从一张包含大约700万条记录的表中获得4个随机结果。另外,我还希望从同一个表中获得按类别过滤的4个随机记录。
现在,正如您所想象的那样,对表进行随机排序会导致查询花费几秒钟,这是不理想的。
我为non-filtered
结果集考虑的另一种方法是让PHP选择1到7,000,000之间的一些随机数,然后使用查询进行IN(...)
只抓取那些行 - 是的,我知道这个方法有一个警告,如果一个具有该id的记录不再存在,你可能会少于4。
但是,上述方法显然不适用于类别过滤,因为PHP不知道哪个记录号属于哪个类别,因此无法选择要从中选择的记录号。
有什么更好的方法可以做到这一点吗?我能想到的唯一方法是将每个类别的记录id存储在另一个表中,然后从中选择随机结果,然后在辅助查询中仅从主表中选择那些记录ID;但我确信有更好的方法!?
答案 0 :(得分:2)
您当然可以使用RAND()
和LIMIT
(对于类别)在查询中使用WHERE
函数。然而,正如您所指出的那样,需要对数据库进行扫描,这需要花费时间,特别是在您的情况下由于数据量的原因。
你的另一个选择,就像你指出的那样,将id / category_id存储在另一个表中可能会更快一些,但同样必须在该表上有一个LIMIT
和WHERE
包含与主表相同数量的记录。
另一种方法(如果适用)是每个类别有一个表并存储ID。如果您的类别是固定的或不经常更改,那么您应该能够使用该方法。在这种情况下,您将有效地从子句中删除WHERE
,并且在每个类别表上获得RAND()
LIMIT
会更快,因为每个类别表将包含来自您的一个记录子集主要表。
其他一些替代方法是仅为该操作使用键/值对数据库。 MongoDb或Google AppEngine可以提供帮助并且非常快。
您也可以在MySQL中使用Master / Slave。从站实时复制内容,但是当您需要执行昂贵的查询时,您会查询从站而不是主站,从而将负载传递给其他计算机。
最后,您可以使用Sphinx,它更易于安装和维护。然后,您可以将每个类别查询视为文档搜索,并让Sphinx随机化结果。这样你可以将这个昂贵的操作偏移到另一个层,让MySQL继续进行其他操作。
只需考虑一些问题。
答案 1 :(得分:1)
使用随机数方法
或者您可以使用union动态生成sql以一步完成查询。
SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
UNION
SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
UNION
SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
UNION
SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
注意:我的sql可能无效,因为我不是mySql人,但理论应该是合理的
答案 2 :(得分:1)
首先,您需要获得行数......就像这样
select count(1) from tbl where category = ?
然后选择一个随机数
$offset = rand(1,$rowsNum);
并选择一个具有偏移的行
select * FROM tbl LIMIT $offset, 1
答案 3 :(得分:-1)
对于MySQl,您可以使用
RAND()
SELECT column FROM table
ORDER BY RAND()
LIMIT 4