我想优化我的查询,所以我调查一下mysql-slow.log.
我的大多数慢查询包含ORDER BY RAND().我无法找到解决此问题的真正解决方案.Theres是MySQLPerformanceBlog的可能解决方案,但我认为这还不够.在未经优化(或经常更新,用户管理)的表上,它不起作用,或者我需要运行两个或更多查询才能选择我PHP生成的随机行.
这个问题有什么解决方案吗?
一个虚拟的例子:
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
ORDER BY
RAND()
LIMIT 1
Run Code Online (Sandbox Code Playgroud) 如何在SQL中使用高效的简单随机样本?有问题的数据库正在运行MySQL; 我的表至少有200,000行,我想要一个大约10,000的简单随机样本.
"明显"的答案是:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
Run Code Online (Sandbox Code Playgroud)
对于大型表来说,这太慢了:它为每一行调用RAND()(已经将它放在O(n)处)并对它们进行排序,最多使它成为O(n lg n).有没有办法比O(n)更快地做到这一点?
注意:正如Andrew Mao在评论中指出的那样,如果您在SQL Server上使用此方法,则应使用T-SQL函数NEWID(),因为RAND()可能会为所有行返回相同的值.
编辑:5年后
我用更大的表再次遇到了这个问题,并最终使用了@ ignorant的解决方案,并进行了两次调整:
要获取表的1000项样本,我计算行并使用frozen_rand列将结果平均下降到10,000行:
SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high
SELECT *
FROM table
WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000
Run Code Online (Sandbox Code Playgroud)
(我的实际实现涉及更多的工作,以确保我没有欠采样,并手动包裹rand_high,但基本的想法是"随机削减你的N到几千.")
虽然这会做出一些牺牲,但它允许我使用索引扫描对数据库进行采样,直到它再次小到ORDER BY RAND()为止.
我已经阅读了MySQL ORDER BY RAND()函数的一些替代方法,但大多数替代方案仅适用于需要单个随机结果的位置.
有没有人知道如何优化返回多个随机结果的查询,例如:
SELECT u.id,
p.photo
FROM users u, profiles p
WHERE p.memberid = u.id
AND p.photo != ''
AND (u.ownership=1 OR u.stamp=1)
ORDER BY RAND()
LIMIT 18
Run Code Online (Sandbox Code Playgroud) 我正在开发一个测验网站,我有一个存储所有问题的数据库.有不同类型的测验,如数学,科学,历史等.所有问题都存储在一个表中.
我的问题表看起来像这样:
questions ( qno(int) ,type(int), question, .... ,... )
Run Code Online (Sandbox Code Playgroud)
qno是主键,type用于跟踪测验类型:
if type = 1 (math)
type = 2(science)
Run Code Online (Sandbox Code Playgroud)
现在,我想为每种类型的测试选择一些随机问题.例如,我可能只想为数学测试选择一些随机的20个问题.
MySQL有某种方法可以选择随机行吗?
可能重复:
从mysql中的大表中快速选择随机行
我已经看到使用这样的查询拉取随机行,这对于大型数据集来说效率很低.
SELECT id FROM table ORDER BY RANDOM() LIMIT 1
Run Code Online (Sandbox Code Playgroud)
我还看到了其他各种与MySQL无关的RDBMS特定解决方案.
我能想到的最好的事情就是使用两个查询并执行类似的操作.
这是SQL:
SELECT COUNT(*) FROM table;
SELECT id FROM table LIMIT randnum, 1;
Run Code Online (Sandbox Code Playgroud)
有没有人有更好的主意?
我想通过随机排序的ActiveRecord模型列表(来自MySQL数据库的行)进行分页.
但是,这种随机化需要在每个会话的基础上持续存在,以便访问该网站的其他人也可以获得随机的,可分页的记录列表.
假设有足够的实体(数万个)将随机排序的ID值存储在会话或cookie中太大,所以我必须暂时以其他方式(MySQL,文件等)保留它.
最初我以为我可以根据会话ID和页面ID创建一个函数(返回该页面的对象ID),但是由于MySQL中的对象ID值不是连续的(有间隙),因此我似乎崩溃了正在戳它.好处是它不需要/最小存储,但缺点是它实现起来可能非常复杂并且可能是CPU密集型的.
我的感觉是我应该创建一个交集表,例如:
random_sorts( sort_id, created_at, user_id NULL if guest)
random_sort_items( sort_id, item_id, position )
Run Code Online (Sandbox Code Playgroud)
然后只需将'sort_id'存储在会话中.然后,我可以像往常一样对random_sorts WHERE sort_id = n ORDER BY position LIMIT ...进行分页.
当然,我必须在那里放一些收割机,以便在一段时间不活动后将它们移除(基于random_sorts.created_at).
不幸的是,我必须在创建新对象时(和/或删除旧对象,尽管删除非常罕见)使排序无效.并且,随着负载的增加,该表的大小/性能(甚至正确索引)会下降.
看起来这应该是一个解决的问题,但我找不到任何这样做的导轨插件......任何想法?谢谢!!
mysql> EXPLAIN SELECT * FROM urls ORDER BY RAND() LIMIT 1;
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
| 1 | SIMPLE | urls | ALL | NULL | NULL | NULL | NULL | 62228 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
Run Code Online (Sandbox Code Playgroud)
以上不符合效率,我该怎么做呢?
UPDATE
似乎使用答案中提到的解决方案仍无济于事:
mysql> explain SELECT *
-> FROM (
-> SELECT @cnt := COUNT(*) + 1,
-> @lim := 10 …Run Code Online (Sandbox Code Playgroud) 我无法正确地为派生表别名设置语法:
SELECT * FROM
(SELECT a.*, b.*
FROM a INNER JOIN b ON a.B_id = b.B_id
WHERE a.flag IS NULL AND b.date < NOW()
UNION
SELECT a.*, b.*
FROM a INNER JOIN b ON a.B_id = b.B_id
INNER JOIN c ON a.C_id = c.C_id
WHERE a.flag IS NOT NULL AND c.date < NOW())
AS t1
ORDER BY RAND() LIMIT 1
Run Code Online (Sandbox Code Playgroud)
我得到一个重复的列名B_id.有什么建议?
我已经阅读了ORDER BY RAND()及其性能问题 - 这些仅适用于返回大型数据集的查询吗?例如,如果我有一个包含100,000行的表并使用WHERE子句返回包含10条记录的数据集,然后使用ORDER BY RAND()LIMIT 1,那么在我的表被过滤到表后,将应用此ORDER BY RAND()记录匹配WHERE子句,因此性能问题可以忽略不计?
我正在创建一个在线商店网站,该网站需要从数据库中选择随机产品的功能.
我们的想法是,每当网页加载时,随机产品的广告就会有所不同!
使用PHP,我将如何做到这一点?
tbl_products
id code title stock cost rrp
这些是我需要从数据库访问的行.
谢谢
可能重复:
MySQL快速从600K行中选择10个随机行
我需要从表中拉出一个随机ID.此时只存在少量记录,但随着时间的推移,它们将会增长.获取此ID的方法是在Php或MySql中,以及它们之间的后果是什么.最后一件事我需要速度和性能.
mysql ×11
random ×6
sql ×5
performance ×2
php ×2
persistence ×1
postgresql ×1
sorting ×1
sql-order-by ×1
union ×1