Ton*_*ony 58 mysql sql random sql-order-by
我已经阅读了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)
Neo*_*ptt 27
此解决方案最适合使用索引列.
这是一个标有100,000行的简单示例和优化查询工作台.
优化:300毫秒
SELECT
g.*
FROM
table g
JOIN
(SELECT
id
FROM
table
WHERE
RAND() < (SELECT
((4 / COUNT(*)) * 10)
FROM
table)
ORDER BY RAND()
LIMIT 4) AS z ON z.id= g.id
Run Code Online (Sandbox Code Playgroud)
关于限制ammount的注意事项:限制4和4 /计数(*).4s需要是相同的数字.改变你返回的数量不会对速度造成太大影响.极限4和极限1000的基准是相同的.限制10,000使其达到600毫秒
关于连接的注意事项:随机化id只比随机化一行更快.因为它必须将整行复制到内存中然后随机化它.连接可以是链接到子查询的任何表,以防止表扫描.
note where子句:where count限制了随机化结果的数量.它需要一定比例的结果并对它们进行排序而不是整个表格.
note子查询:如果要执行连接和额外的where子句条件,则需要将它们放在子查询和子查询中.准确计数并撤回正确的数据.
未优化:1200ms
SELECT
g.*
FROM
table g
ORDER BY RAND()
LIMIT 4
Run Code Online (Sandbox Code Playgroud)
PROS
快4倍order by rand().此解决方案可以与任何带有索引列的表一起使用.
缺点
复杂的查询有点复杂.需要在子查询中维护2个代码库
OMG*_*ies 20
这是另一种选择,但它仍然基于使用RAND():
SELECT u.id,
p.photo,
ROUND(RAND() * x.m_id) 'rand_ind'
FROM users u,
profiles p,
(SELECT MAX(t.id) 'm_id'
FROM USERS t) x
WHERE p.memberid = u.id
AND p.photo != ''
AND (u.ownership=1 OR u.stamp=1)
ORDER BY rand_ind
LIMIT 18
Run Code Online (Sandbox Code Playgroud)
这稍微复杂一点,但更好地分配了random_ind值:
SELECT u.id,
p.photo,
FLOOR(1 + RAND() * x.m_id) 'rand_ind'
FROM users u,
profiles p,
(SELECT MAX(t.id) - 1 'm_id'
FROM USERS t) x
WHERE p.memberid = u.id
AND p.photo != ''
AND (u.ownership=1 OR u.stamp=1)
ORDER BY rand_ind
LIMIT 18
Run Code Online (Sandbox Code Playgroud)
它不是最快的,但速度快于普通ORDER BY RAND()方式:
ORDER BY RAND()当你用它来查找索引列时,并不是那么慢.您可以在一个查询中获取所有ID,如下所示:
SELECT id
FROM testTable
ORDER BY RAND();
Run Code Online (Sandbox Code Playgroud)
获取一系列随机ID,并将JOIN结果与其他SELECT或WHERE参数的另一个查询:
SELECT t.*
FROM testTable t
JOIN
(SELECT id
FROM `testTable`
ORDER BY RAND()) AS z ON z.id= t.id
WHERE t.isVisible = 1
LIMIT 100;
Run Code Online (Sandbox Code Playgroud)
在你的情况下,它将是:
SELECT u.id, p.photo
FROM users u, profiles p
JOIN
(SELECT id
FROM users
ORDER BY RAND()) AS z ON z.id = u.id
WHERE p.memberid = u.id
AND p.photo != ''
AND (u.ownership=1 OR u.stamp=1)
LIMIT 18
Run Code Online (Sandbox Code Playgroud)
这是非常生硬的方法,对于非常大的表来说可能不合适,但它仍然比普通表更快RAND().我的执行时间比搜索3000个随机行快了近40倍.
| 归档时间: |
|
| 查看次数: |
83491 次 |
| 最近记录: |