mysql - 我想从 MYSQL 数据库中提取一个随机 ID

标签 mysql performance database-tuning

我想从数据库中随机抽取一篇有图片的文章。

SELECT FLOOR(MAX(id) * RAND()) FROM `table` WHERE `picture` IS NOT NULL

我的表有 33 MB 大,有 1,006,394 篇文章,但只有 816 篇有图片。 我的问题是这个查询需要 0.4640 sek

我需要它更快。 欢迎任何想法。

附言 1.当然我有一个关于id的索引。 2.图片字段没有索引。我应该加一个吗? 3.产品名称是唯一的,产品编号也是唯一的,但这是不可能的。

测试结果。

@cHao 的解决方案在我使用它来选择带有图片的随机条目之一时更快。(然后 0.1 秒。 但如果我尝试做相反的事情,选择一篇没有图片的随机文章,速度会更慢。 2..3 秒

@Kickstart 的解决方案在尝试查找带图片的条目时速度稍慢,但在尝试查找不带图片的条目时速度几乎相同。平均 0,149 秒。

@bob-kruithof 的解决方案对我不起作用。 当试图找到一个有图片的条目时,它会选择一个没有图片的条目。

@ganesh-bora,是的,你是对的,在我的例子中,速度差异大约是 5..15 倍。

我要感谢大家的帮助,我决定@Kickstart。

最佳答案

您需要获取具有匹配记录的值范围,然后在该范围内找到匹配记录。

像这样:-

SELECT r1.id
FROM `table` AS r1 
INNER JOIN (
    SELECT RAND( ) * ( MAX( id ) - MIN( id ) ) + MIN( id ) AS id
    FROM `table`
    WHERE `picture` IS NOT NULL
) AS r2
ON r1.id >= r2.id
WHERE `picture` IS NOT NULL
ORDER BY r1.id ASC
LIMIT 1

然而,为了提高效率,您需要在正在检查的字段上建立索引(即,在您的示例中为 picture)

只是解释这是如何工作的。

子选择从表中找到一个随机 ID,该 ID 介于图片记录的最小 ID 和最大 ID 之间。这个随机 ID 可能是也可能不是图片。

这个子选择的结果 id 与主表连接回来,但是使用 >= 和一个指定记录是图片记录的 WHERE 子句。因此它加入了id大于或等于随机id的所有图片记录。最高的随机 id 将是具有最高 id 的图片记录的那个,所以它总是会找到一条记录(如果有任何图片记录)。然后使用 ORDER BY/LIMIT 取回该单个 ID。

请注意,这有一个明显的缺陷,但大多数时候它是无关紧要的。检索到的记录可能不是完全随机的。 id 最低的图片不太可能被返回(只有当 RAND() 恰好返回 0 时才会返回),但如果这很重要,这很容易通过四舍五入生成的随机 id 来修复。另一个缺陷是,如果 id 在整个 id 范围内不是模糊地均匀分布,那么某些 id 将比其他 id 更频繁地返回。例如,前 1000 个 id 是图片,然后直到最后一个(第 3300 万)条记录。随机 ID 可以是这 3300 万中的任何一个,但除非它小于或等于 1000,否则它将是返回的第 3300 万条记录。

关于mysql - 我想从 MYSQL 数据库中提取一个随机 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16457687/

相关文章:

由于 WHERE 过滤器,来自多个表的 MySQL 请求变慢

mysql - 哪个数据库是面向性能的,MySQL 还是 MariaDB?

php - json 返回损坏的数据

php - 单个 php 文件中的多个表单

Python 搜索文件中的一百万个字符串并统计每个字符串的出现次数

javascript - 优化 jQuery 以避免 Safari : “This webpage is using significant energy...”

python - 如何使用 Python 的 timeit 为代码段计时以测试性能?

oracle - 加快 Oracle Text 索引或让索引器仅在低加载时间下工作

python - 高效地将数据结构添加到数据库中

mysql - 使用 jugglingdb 选择另一个表中存在 id 的结果