在MySQL中使用RAND()从巨大的表中获取单个随机行非常慢:
SELECT quote FROM quotes ORDER BY RAND() LIMIT 1
Here is an article关于此问题及其原因。
他们的解决方案是使用两个查询:
SELECT COUNT(*) AS cnt FROM quotes
- Use result to generate a number between 0 and COUNT(*)
SELECT quote FROM quotes LIMIT $generated_number, 1
我想知道,这是否只能在一个查询中实现。
所以我的方法是:
SELECT * FROM quotes
LIMIT (
ROUND(
(SELECT COUNT(*) FROM quotes) * RAND()
)
), 1
但它接缝MySQL不允许在Limit内的任何逻辑。 虽然我找不到关于这个主题的任何信息,但是否属实。
所以我的问题:
答案 0 :(得分:5)
是否有理由不能使用存储过程来创建预准备语句?
DELIMITER //
DROP PROCEDURE IF EXISTS rand_quote//
CREATE PROCEDURE rand_quote()
BEGIN
SET @rand := ROUND((SELECT COUNT(*) FROM quotes) * RAND());
SET @sql := CONCAT('SELECT * FROM quotes LIMIT ', @rand, ', 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
//
DELIMITER ;
答案 1 :(得分:1)
我只是想到了这个,接缝就像一个解决方案:
SELECT * FROM quotes
WHERE quotes_id = ROUND(
(SELECT COUNT(*) FROM quotes) * RAND()
)
LIMIT 1
但只有当quotes_id没有间隙时才会起作用。
答案 2 :(得分:1)
我通过检查max id解决了这个问题。然后我做了rand(0,max_id)的php循环,它检查对象是否存在。完成。
比之前的兰德订购快得多。