我有下一个查询:
SELECT `real_estates`.*
FROM `real_estates`
WHERE (photos_count > 0) AND
(price > 0) AND
(longitude is not null AND latitude is not null) AND
`real_estates`.`rent` = 0 AND
(estate_type = 0 or estate_type = 1) AND
(price > 1000)
ORDER BY RAND()
LIMIT 1
DB是MySQL。real_estates
表中生产数据库和本地数据库的行数约为200k。但在开发机器上,当生产给我25秒(!)的等待时间时,运行这个查询需要0.5秒。
表引擎是InnoDB,EXPLAIN
在两个系统上给出相同的结果。如果我删除ORDER BY RAND(),它会占用产品的正常运行时间。有什么想法吗?
从查询中,您似乎正在尝试从real_estates
表中检索随机选择的行。按照您编写查询的方式,MySQL服务器必须将所有匹配的行加载到RAM,或者硬盘驱动器,数据结构中,然后对它们进行排序,取第一行,然后丢弃其余行。很可能您的共享生产服务器的可用RAM量要小得多,磁盘驱动器速度较慢,有很多其他用户,或者这三个都有。这意味着像你这样的RAM密集型任务可能会被迫进入磁盘。这会减慢速度。很多。你已经知道了。
您可以考虑对查询进行此重构。
SELECT `real_estates`.*
FROM `real_estates`
JOIN (
SELECT id
FROM real_estates
WHERE (photos_count > 0) AND
(price > 0) AND
(longitude is not null AND latitude is not null) AND
`real_estates`.`rent` = 0 AND
(estate_type = 0 or estate_type = 1) AND
(price > 1000)
ORDER BY RAND()
LIMIT 1
) r ON real_estates.id = r.id
(我猜您的表每行都有一个唯一的id
值。我还猜它被称为id
。您可能需要更改此查询以匹配您的id的实际名称。)
内部查询包含您的选择逻辑。但是,它并没有生成一整堆要排序的数据,而是只生成id
值。然后,它随机订购它们,并取第一个。最后,连接会占用整个选定的行。
ORDER BY RAND()是一个糟糕的解决方案。您的索引将被忽略。数据量大的情况特别困难。
您可以使用主键代替RAND()。