繁体   English   中英

如何加快简单的 rails 数据库查询速度?

[英]How can I speed up a simple rails database query?

我在 ruby​​ 2.6.3 上使用 rails 4.2.11.1

我使用 Rails 的请求非常慢,所以我对我的代码进行了基准测试并找到了罪魁祸首。 大多数减速发生在数据库调用中,我从数据库的表中选择一行。 我已经尝试了相同想法的几个不同版本

使用这个版本

Rails.logger.info Benchmark.measure{
  result = Record.find_by_sql(['SELECT column FROM table WHERE condition']).first.column
}

rails 输出说 sql 需要 54.5 毫秒,但基准测试打印出 0.043427 0.006294 0.049721 ( 1.795859),总请求需要 1.81 秒。 当我直接在我的 postgres 终端中运行上面的 sql 时,它需要 42ms。

显然问题不是我的sql慢。 42 毫秒并不明显。 但是 1.79 秒太慢了,并且会造成糟糕的用户体验。

我做了一些阅读并得出结论,减速是由 rails 的对象创建引起的(这看起来很奇怪,但显然这可能非常慢)所以我尝试使用 pluck 来最小化创建的对象数量:

Rails.logger.info Benchmark.measure{
    result = Record.where(condition).pluck(column).first
}

现在 rails 说 sql 用了 29.3ms,基准测试给出了 0.017989 0.006119 0.024108 ( 0.713973) 整个请求用了 0.731 秒。 这是一个巨大的改进,但 0.7 秒仍然是一个严重的减速,并且仍然破坏了我的应用程序的可用性。

我究竟做错了什么? 在我看来,如此简单的事情竟然会出现如此巨大的放缓,这似乎很疯狂。 如果这就是 rails 的工作方式,我无法想象有人将它用于严肃的应用程序!

find_by_sql对您的数据库执行自定义 SQL 查询并返回所有结果。

这意味着您的数据库中的所有记录都将被返回并实例化。 只有这样,您才能通过first调用结果来从该数组中选择第一个。

当您first调用 ActiveRecord::Relation 时,它会为您的查询添加一个限制并仅选择那个,这是您想要的行为。

这意味着您应该自己限制查询:

  result = Record.find_by_sql(['SELECT column FROM table WHERE condition LIMIT 1']).first.column

我很确定您的请求会很快,因为 ruby​​ 不需要实例化所有结果行。

正如我上面提到的,如果你只想要第一个,不知道为什么要要求所有的匹配。

如果我做:

 Rails.logger.info Benchmark.measure{
   result = User.where(email: 'foo@bar.com').pluck(:email).first 
 }

(9.6ms)  SELECT "users"."email" FROM "users" WHERE "users"."email" = $1  [["email", "foo@bar.com"]]
#<Benchmark::Tms:0x00007fc2ce4b7998 @label="", @real=0.6364280000561848,     @cstime=0.00364, @cutime=0.000661, @stime=0.1469640000000001, @utime=0.1646029999999996, @total=0.3158679999999997>

 Rails.logger.info Benchmark.measure{
   result = User.where(email: 'foo@bar.com').limit(1).pluck(:email) 
 }

 (1.8ms)  SELECT  "users"."email" FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "foo@bar.com.com"], ["LIMIT", 1]]
#<Benchmark::Tms:0x00007fc2ce4cd838 @label="", @real=0.004004000045824796, @cstime=0.0, @cutime=0.0, @stime=0.0005539999999997214, @utime=0.0013550000000002171, @total=0.0019089999999999385>

Rails 也可以兑现。 如果您再次运行查询,第二次应该会更快。 你的where条件有多复杂? 这可能是其中的一部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM