Rails 3.1 - Heroku上mySQL和PostgreSQL之间的巨大查询时间差异

时间:2012-01-09 23:16:36

标签: mysql sql postgresql ruby-on-rails-3.1 heroku

我的开发环境中有一个查询,通常需要 1.7 ms 才能在dev mySQL数据库上运行。当碰到Heroku和PostgreSQL时,同一数据集上的相同查询大约需要 1.2秒

SELECT distinct user_id, score, quality 
FROM `reports` 
WHERE (datetime_utc >= '2012-01-13 14:00:00' AND 
       datetime_utc <= '2012-01-14 14:00:00') 
ORDER BY score DESC, quality DESC LIMIT 20

我创建了一个关于得分和质量的复合索引,它有助于SQL版本,但是在PostgreSQL上运行的查询仍然非常非常慢。我的第一直觉是检查索引实际上是否在Heroku方面,但我不知道该怎么做 - 无论如何,我觉得这更多地与mySQL和PostgreSQL不相关的事实有关不做同样的事情。

任何见解或指示都会非常感激!

3 个答案:

答案 0 :(得分:2)

尝试此修改后的查询:

SELECT user_id, score, quality
FROM   reports
WHERE  datetime_utc BETWEEN '2012-01-13 14:00:00' AND '2012-01-14 14:00:00'
GROUP  BY user_id, score, quality
ORDER  BY score DESC, quality DESC
LIMIT  20
  • 由于最后应用了DISTINCT,因此可能比具有许多非明显行的GROUP BY慢。您必须使用EXPLAIN ANALYZE进行测试。否则,结果是一样的。

  • 使用BETWEEN对WHERE子句进行少量简化。删除了非标准的MySQL语法。

  • (score, quality)上的索引很难使用。这里的有用索引(在大多数情况下应该会有很大的不同):

CREATE INDEX reports_date_time_utc_idx ON reports (date_time_utc)

重要的部分是指数。

答案 1 :(得分:1)

性能上的差异可能是由dev和heroku之间的数据集大小引起的吗?

如果有一个分数索引,如果有很多行,质量将无济于事,因为它仍然必须根据datetime_utc进行过滤。

您可能希望考虑datetime_utc上的索引,因为它需要先在那里进行过滤。

如果你真的想要优化读取速度,你可以在datetime_utc,score,quality,user_id上有一个复合索引,这将完全消除查找行数据的需要。

但是,请注意这样做,因为您可能会在具有如此宽索引的插入上导致热点。

答案 2 :(得分:1)

由于Heroku不允许您连接到数据库,除非拥有&gt; 200 $ /月计划之一,您可以尝试检索数据库的本地副本以供本地检查。

heroku db:pull // Will give you a local copy of the db

结果将是这样的:

Receiving schema
Receiving data
8 tables, 591 records
users:         100% |================================| Time: 00:00:00
pages:         100% |================================| Time: 00:00:00
comments:      100% |================================| Time: 00:00:00
tags:          100% |================================| Time: 00:00:00
Receiving indexes
Resetting sequences