簡體   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