我正在试图弄清楚为什么我的rails应用程序中的一个查询的表现相当不同。我正在使用Postgres 9.3,并使用jRuby 1.7.10使用rails 4.0.3,这可能是JDBC驱动程序的一个问题?
但基本上,这是一个非常简单的查询:
SELECT * FROM table;
该表包含851
行,因此它几乎不是一个庞大的数据集,所以我期待快速查询。当我在pgAdmin 3中执行此查询时,我得到了我期望的结果:所有行返回15到35ms之间的任何位置。好又快!
然而,从轨道来看,这是一个不同的故事。在rails控制台中运行查询,我能够实现的最快速度是189ms
,同时通常在200ms
标记附近。通过调用Table.all
我最初的想法只是ActiveRecord在851对象的实例化中增加了开销,所以这显然会减慢它的速度。为了测试这个,我跑了
ActiveRecord::Base.connection.execute("SELECT * FROM table")
有一点点加速,但几乎所有查询都在150ms
左右,距离pgAdmin标记还有很长一段路要走。作为我尝试的最后一次尝试
ActiveRecord::Base.connection.exec_query_raw("SELECT * FROM table")
但这并没有改善表现。
我现在真的很难过为什么这么慢,因为我看到pgAdmin和Rails之间的性能下降了10倍。在Rails中只执行了原始SQL,我知道ActiveRecord不会减慢速度,所以我现在真的很困惑。
有谁知道为什么这比它应该慢得多?
更新
我已经做了一些挖掘,似乎是rails处理Date字段的方式。如果我手动选择表中的所有列,它同样慢,但如果我选择除updated_at
和created_at
以外的所有列,查询将在2-4毫秒左右运行,这是完美的!
我现在唯一的问题是如何解决这个问题。有没有办法解决日期的rails性能问题,或者有轨道没有将它们解析为日期并将它们保存为字符串或类似的东西?
更新2
所以在做了一些挖掘并且@stonehz指出我从这篇文章中提到的错误之后,我已经升级到Jruby 1.7.12
和rails 4.1.0
并注意到了相当快的速度。它与pgAdmin的性能并没有太大关系,但我认为如果不完全删除日期列,我就不会得到更好的结果。以下是我现在的基准
SELECT *: 4.080000 0.330000 4.410000 ( 5.243000)
SELECT date_fields: 1.960000 0.020000 1.980000 ( 2.032000)
SELECT * - date_fields: 3.070000 0.070000 3.140000 ( 3.247000)
--------------------------------------------------------- total: 9.530000sec
user system total real
SELECT *: 3.700000 0.060000 3.760000 ( 4.663000)
SELECT date_fields: 1.790000 0.020000 1.810000 ( 2.021000)
SELECT * - date_fields: 2.330000 0.060000 2.390000 ( 3.180000)
此基准测试查询851行。第一个测试是一个简单的SELECT *
语句。第二个测试仅选择日期字段,最终测试选择日期字段的所有字段除。每个查询都运行100次以获得最终结果。
如图所示,select *
语句现在只需要约4秒就可以运行100次,因此每个查询只占用40ms
,这更接近〜30ms的pgAdmin时间。好多了!
答案 0 :(得分:1)
他们已经解决了这个问题,并围绕您找到的错误打开了几张票:
https://github.com/jruby/jruby/issues/1662
https://github.com/jruby/activerecord-jdbc-adapter/issues/540
使用Jruby 1.7.12将提高5倍左右的性能(正如他们的基准所暗示的那样)
答案 1 :(得分:0)
我现在真的很难过为什么这么慢,因为我看到pgAdmin和Rails之间的性能下降了10倍。在Rails中只执行了原始SQL,我知道ActiveRecord不会减慢速度,所以我现在真的很困惑。
与你的查询一样,它不是ActiveRecord。
当您在pg admin中运行此查询时,在我知道的情况下,它实际运行它。 PgAdmin对你的用法做了一些假设,即你最终会得到一个庞大的集合。为了提高性能,更有趣的是使用游标以便允许您通过根据需要而不是一次性获取行来导航庞大的集合。我知道这正是发生的事情。
相反,当您在应用中运行相同的查询时,您将负责执行此类操作。或者就此而言,不要开始运行这种查询。需要从数据库表中选择所有行通常表明应用程序设计中存在错误。