我有下一个查询:
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(),则需要正常运行时间。有什么想法吗?
答案 0 :(得分:3)
从您的查询中,您似乎正在尝试从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
个值。然后它随机地命令它们并取第一个。最后,联接抓住了整个选定的行。
答案 1 :(得分:0)
ORDER BY RAND()是不好的解决方案。您的索引将被忽略。大量数据特别困难的情况。
您可以使用RAND()的主键。