SQL查询在本地数据库和生产之间运行时间的难以置信的差异

时间:2015-12-30 12:29:31

标签: mysql sql ruby-on-rails database

我有下一个查询:

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(),则需要正常运行时间。有什么想法吗?

2 个答案:

答案 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()的主键。