Mysql 在不扫描整个数据库的情况下获取随机帖子
如何在不扫描整个数据库的情况下获得随机帖子 我知道,如果使用MySQLMysql 在不扫描整个数据库的情况下获取随机帖子,mysql,Mysql,如何在不扫描整个数据库的情况下获得随机帖子 我知道,如果使用MySQLorderbyrand()它将扫描整个数据库 如果有任何其他方法可以在不扫描整个数据库的情况下执行此操作。许多人似乎相信,ORDER BY RAND()在某种程度上可以在不扫描整个表的情况下生成结果 事实并非如此。事实上,它可能比按列值排序慢,因为MySQL必须为每一行调用RAND()函数 为了演示,我制作了一个包含50万MD5哈希的简单表: mysql> select count(*) from delete_me;
orderbyrand()
它将扫描整个数据库
如果有任何其他方法可以在不扫描整个数据库的情况下执行此操作。许多人似乎相信,
ORDER BY RAND()
在某种程度上可以在不扫描整个表的情况下生成结果
事实并非如此。事实上,它可能比按列值排序慢,因为MySQL必须为每一行调用RAND()函数
为了演示,我制作了一个包含50万MD5哈希的简单表:
mysql> select count(*) from delete_me;
+----------+
| count(*) |
+----------+
| 500000 |
+----------+
1 row in set (0.00 sec)
mysql> explain delete_me;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| txt | text | NO | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.12 sec)
mysql> select * from delete_me limit 4;
+----+----------------------------------+
| id | txt |
+----+----------------------------------+
| 1 | 9b912c03d87991b71955a6cd4f81a299 |
| 2 | f1b7ddeb1c1a14265a620b8f2366a22e |
| 3 | 067b39538b767e2382e557386cba37d9 |
| 4 | 1a27619c1d2bb8fa583813fdd948e94c |
+----+----------------------------------+
4 rows in set (0.00 sec)
使用ORDER BY RAND()
从该表中随机选择一行需要我的计算机1.95秒
mysql> select * from delete_me order by rand() limit 1;
+--------+----------------------------------+
| id | txt |
+--------+----------------------------------+
| 446149 | b5f82dd78a171abe6f7bcd024bf662e8 |
+--------+----------------------------------+
1 row in set (1.95 sec)
但按升序排列文本字段只需0.8秒
mysql> select * from delete_me order by txt asc limit 1;
+-------+----------------------------------+
| id | txt |
+-------+----------------------------------+
| 88583 | 00001e65c830f5b662ae710f11ae369f |
+-------+----------------------------------+
1 row in set (0.80 sec)
由于此表中的id值从1开始按顺序编号,因此我可以更快地选择一个随机行,如下所示:
mysql> select * from delete_me where id=floor(1+rand()*500000) limit 1;
+-------+----------------------------------+
| id | txt |
+-------+----------------------------------+
| 37600 | 3b8aaaf88af68ca0c6eccff7e61e897a |
+-------+----------------------------------+
1 row in set (0.02 sec)
但在一般情况下,我建议在@deceze链接的页面中使用。我对此类要求的建议是使用MD5哈希
SELECT * FROM myTable WHERE md5Col > MD5(NOW()) LIMIT 1
- 如果SELECT查询中的MD5导致哈希值大于表中的最后一条记录,则可能无法从查询中获得任何记录。如果发生这种情况,您总是可以使用新的哈希重新查询它
- 在每个记录上有一个固定的MD5散列意味着这些记录的顺序是固定的。如果您一次只获取一条记录,那么这并不是一个真正的问题,但是如果您使用它来获取多组记录,那么可能会注意到这一点。如果需要,您当然可以通过在加载记录时重新对其进行灰化来更正此问题
@squamish ossifrage
解决方案的一个微小修改-假设在具有数值的表中存在主键:
SELECT *
FROM delete_me
WHERE id >= Round( Rand() *
( SELECT Max( id ) FROM test ))
LIMIT 1
对于包含超过50000行的表,查询将在100毫秒内运行:
mysql> SELECT id, table_schema, table_name
FROM delete_me
WHERE id >= Round( Rand() *
( SELECT Max( id ) FROM delete_me ))
LIMIT 1;
+-----+--------------------+------------+
| id | table_schema | table_name |
+-----+--------------------+------------+
| 173 | information_schema | PLUGINS |
+-----+--------------------+------------+
1 row in set (0.01 sec)
使用
ORDER BY RAND()LIMIT 1
。@Joke仍然会对整个表进行排序,这正是OP不想要的。@如果他正在查找单行结果,则不会进行排序。@Joke它会首先对整个表进行排序,然后从中返回第一个结果!所有的orderby
子句都会这样做,否则您将无法得到正确的结果。这是一项昂贵的手术,众所周知,这是一项昂贵的手术,也是手术医生提出这个问题的原因。@deceze可能是我错了,但我从以下参考文献中得出结论:1。正如你所指出的,你的帖子中提供的唯一答案在现实生活中是不适用的。2.为了演示,必须解释查询,而不是表。如果您可能需要至少使用两个查询,。。。限制n,1
其中n≤ <代码>计数(*)似乎更直截了当。不过这是一个有趣的方法。