我正在使用的解决方案也发布在下面的链接中:我如何优化MySQL的ORDER BY RAND()函数?
我假设您的用户表将大于您的配置文件表,如果不是,则为1到1的基数。
如果是这样,我将首先在用户表上进行随机选择,然后再加入配置文件表。
首先选择:
SELECT *
FROM users
WHERE users.ownership = 1 OR users.stamp = 1
然后从该池中,通过计算的概率选择随机行。 如果您的表有M行,并且您想挑选出N个随机行,则随机选择的概率应为N / M。 因此:
SELECT *
FROM
(
SELECT *
FROM users
WHERE users.ownership = 1 OR users.stamp = 1
) as U
WHERE
rand() <= $limitCount / (SELECT count(*) FROM users WHERE users.ownership = 1 OR users.stamp = 1)
其中N是$ limitCount,M是计算表行数的子查询。 但是,由于我们正在研究概率,因此返回的行可能少于$ limitCount。 因此,我们应将N乘以一个因子以增加随机池的大小。
即:
SELECT*
FROM
(
SELECT *
FROM users
WHERE users.ownership = 1 OR users.stamp = 1
) as U
WHERE
rand() <= $limitCount * $factor / (SELECT count(*) FROM users WHERE users.ownership = 1 OR users.stamp = 1)
我通常将$ factor = 2设置。您可以将因子设置为较低的值,以进一步减小随机池的大小(例如1.5)。
此时,我们已经将M大小表限制为大约2N大小。 从这里我们可以先进行JOIN然后进行LIMIT。
SELECT *
FROM
(
SELECT *
FROM
(
SELECT *
FROM users
WHERE users.ownership = 1 OR users.stamp = 1
) as U
WHERE
rand() <= $limitCount * $factor / (SELECT count(*) FROM users WHERE users.ownership = 1 OR users.stamp = 1)
) as randUser
JOIN profiles
ON randUser.id = profiles.memberid AND profiles.photo != ''
LIMIT $limitCount
在大表上,此查询的性能将优于RAND()查询的常规ORDER。
希望这可以帮助!