Ruby on rails 在Heroku上运行缓慢的简单Postgres查询
我有一个Ruby on rails 在Heroku上运行缓慢的简单Postgres查询,ruby-on-rails,postgresql,activerecord,heroku,postgresql-performance,Ruby On Rails,Postgresql,Activerecord,Heroku,Postgresql Performance,我有一个电影型号,大约15000件,还有一个Dvd型号,3500件 以下查询是使用运行在Heroku上的Crane Postgres db的简单Rails关联。我想知道为什么下面的查询需要这么长时间,以及如何最终缩短查询时间 2012-10-24T05:42:19+00:00 app[postgres]: [30-1] [BLACK] LOG: duration: 57.914 ms statement: SELECT "movies".* FROM "movies" WHERE "mo
电影
型号,大约15000件,还有一个Dvd
型号,3500件
以下查询是使用运行在Heroku上的Crane Postgres db的简单Rails关联。我想知道为什么下面的查询需要这么长时间,以及如何最终缩短查询时间
2012-10-24T05:42:19+00:00 app[postgres]: [30-1] [BLACK] LOG: duration: 57.914 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 37 ORDER BY scene LIMIT 1
2012-10-24T05:42:20+00:00 app[postgres]: [31-1] [BLACK] LOG: duration: 77.086 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 915 ORDER BY scene LIMIT 1
2012-10-24T05:42:20+00:00 app[postgres]: [32-1] [BLACK] LOG: duration: 85.602 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 108 ORDER BY scene LIMIT 1
2012-10-24T05:42:21+00:00 app[postgres]: [33-1] [BLACK] LOG: duration: 70.147 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 11 ORDER BY scene LIMIT 1
2012-10-24T05:42:21+00:00 app[postgres]: [34-1] [BLACK] LOG: duration: 144.204 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 6 ORDER BY scene LIMIT 1
2012-10-24T05:42:22+00:00 app[postgres]: [35-1] [BLACK] LOG: duration: 56.623 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 1956 ORDER BY scene LIMIT 1
2012-10-24T05:42:23+00:00 app[postgres]: [36-1] [BLACK] LOG: duration: 64.860 ms statement: SELECT "movies".* FROM "movies" WHERE "movies"."dvd_id" = 747 ORDER BY scene LIMIT 1
您可以直接连接到数据库CLI,然后使用PostgresQL
EXPLAIN
命令获取有关如何运行查询的信息。这可以显示可以向表添加索引以加快速度的位置。Postgres解释(请看我在那里做了什么?更详细地解释。您负责这些查询的代码是什么?您使用的是即时加载吗?您的查询应该类似于:
DVD.包括(:电影)。在哪里(无论什么)#假设DVD有很多电影
这将减少查询/请求的数量。到您的数据库。您的查询表明您可能有N+1问题
您还应该在movies表中为dvd\u id设置一个数据库索引,因为它是一个外键。确保您至少有dvd\u id的索引。
如果您可以在(dvd_id,场景)上创建复合索引,那么您的查询将是完全优化的,无法进一步优化
换句话说,就是执行
CREATE INDEX movies_dvd_id_scene_idx ON movies (dvd_id, scene);
你应该准备好了
duration: 57.914 ms
duration: 77.086 ms
duration: 85.602 ms
duration: 70.147 ms
duration: 144.204 ms
duration: 56.623 ms
duration: 64.860 ms
平均而言(~80ms),这是在不同大陆上运行的查询通常需要的持续时间。确保你的Heroku应用程序和数据库都位于同一地区(欧盟或美国)。你说“完全最优”,好像这样的事情可以在抽象中确定,而不是通过使用实际数据、生产查询尸体和系统运行的硬件约束进行严格测试。例如:向索引中添加第二个字段会使键的大小变大,从而降低索引块中的键密度。这会使完全缓存索引变得更加困难,或者导致索引树深度更快地增加,从而需要额外的搜索来满足查询。如果scenes/dvd_id的平均基数接近1,那么额外的字段几乎永远不会有好处。我大体上同意。但是,在这种情况下,考虑到数据量(仅15k行),使用此配方不可能造成伤害,并且不需要任何修改和重新要求OP提供更多信息。从这个意义上说,它是完全最优的。请在此处显示解释(缓冲区,分析)
和其他要求的信息: