优化缓慢的ORDER BY RAND()查询

hol*_*fix 1 mysql random

我有一个正在使用的查询,ORDER BY RAND()但它需要太长时间,随着数据的增长,它会变得更糟.

查询连接两个表,它返回5个随机产品和每个产品的随机图像

表1 - 产品

product_id - pk auto-inc
name 
description
Run Code Online (Sandbox Code Playgroud)

数据

1 - product 1 - description
2 - product 2 - description
Run Code Online (Sandbox Code Playgroud)

表2 - ProductImages

image_id   - pk auto-inc
product_id - fk index
filename
Run Code Online (Sandbox Code Playgroud)

数据

1 - 1 - product 1 image
2 - 1 - product 1 image
3 - 1 - product 1 image
4 - 2 - product 2 image
Run Code Online (Sandbox Code Playgroud)

...

我读过这个这个,但不能找到一种方法来优化查询所以我寻求帮助.提前致谢.

Arn*_*anc 5

ORDER BY RAND()因为DBMS必须读取所有行,将它们全部排序,只是为了保留几行,所以速度很慢.因此,此查询的性能在很大程度上取决于表中的行数,并随着行数的增加而减少.

没有办法优化它.

但是有其他选择:

您可以通过执行6次查询来实现"获取5个随机行":

  • 获取表中的行数(可以缓存此行)
  • 做5个查询OFFSET <random offset from 0 to $number_of_rows-1> LIMIT 1(即从一些随机偏移中读取并返回一行)

    例如:( SELECT * FROM Products OFFSET 42 LIMIT 1注意:暂不加入)

    这样的查询非常快,并且在几乎与表大小无关的时间内运行.

这应该是很多比快ORDER BY RAND().


现在,为每个随机产品获取一个随机图像:

SELECT *
FROM (
    SELECT *
    FROM Products
    OFFSET 42 LIMIT 1
) p
JOIN ProductImages pi
ON   pi.product_id = p.id
ORDER BY RAND()
LIMIT 1
Run Code Online (Sandbox Code Playgroud)

内部查询仍然很快,外部只排序几行(假设每个产品的图像很少),因此仍然可以使用rand()的顺序.