2016-08-03 56 views
10

我的Rails應用程序出現問題,其中一些隨機查詢需要大約5秒或更長時間才能完成。大多數時候查詢都非常簡單(select * from x where id = ?),並且這些字段甚至被索引。Rails查詢執行導致數據庫峯值

以下是關於設置一些更多的信息:

  • 彪馬3.5.0背後反轉的nginx代理
    • 4個工人至少有4位,每個最多8個線程。
  • 的Ruby V2.2.3,Rails的V4.2.4
  • 的PostgreSQL數據庫9.4
    • 線程池設置爲最高60個連接
  • Appsignal監測
  • 8GB RAM,4個CPU的,SSD。

我在查看Appsignal中的查詢性能時發現這一點。我注意到大多數查詢在幾個毫秒內完成,然後每隔一段時間,仍然在同一個請求中,有多個查詢需要5秒鐘才能完成。而奇怪的是,它總是需要5秒.. 下面是在動作的圖片: Appsignal performance

事情我已經嘗試:

  • 增加線程池,以確保彪馬工作線程有足夠的連接對象。
  • 將'reaping_frequency'設置爲10秒,以確保沒有使用死連接。
  • 增加彪馬工人/線程

,因爲有一些網頁需要較長的時間來加載(我有一個函數調用,約需要1分鐘才能完成),不知何故,我在應用程序中注意到這個這阻止了新的請求。這對我來說很奇怪,因爲有4個工作者,每個工作者有8個線程= 32個線程,可以處理其他請求。

我跑在上面的圖片中的查詢的解釋,這是輸出:

Limit (cost=0.28..8.30 rows=1 width=150) 
    -> Index Scan using index_addresses_on_addressable_id_and_addressable_type on addresses (cost=0.28..8.30 rows=1 width=150) 
     Index Cond: ((addressable_id = 1) AND ((addressable_type)::text = 'University'::text)) 
     Filter: (deleted_at IS NULL) 
Total query runtime: 13 ms 

這是地址表的架構:

# Table name: addresses 
# 
# id    :integer   not null, primary key 
# street   :string 
# zip_code   :string 
# city    :string 
# country   :string 
# addressable_id :integer 
# addressable_type :string 
# created_at  :datetime   not null 
# updated_at  :datetime   not null 
# street_number :string 
# latitude   :float 
# longitude  :float 
# mobile   :string 
# phone   :string 
# email   :string 
# deleted_at  :datetime 
# name    :string` 

這是我的彪馬配置文件:

#!/usr/bin/env puma 

directory '/home/deployer/apps/qeystate/current' 
rackup "/home/deployer/apps/qeystate/current/config.ru" 
environment 'staging' 
pidfile "/home/deployer/apps/qeystate/shared/tmp/pids/puma.pid" 
state_path "/home/deployer/apps/qeystate/shared/tmp/pids/puma.state" 
stdout_redirect '/home/deployer/apps/qeystate/shared/log/puma_access.log', '/home/deployer/apps/qeystate/shared/log/puma_error.log', true 
threads 4,8 
bind 'unix:///home/deployer/apps/qeystate/shared/tmp/sockets/puma.sock' 
workers 4 
preload_app! 
prune_bundler 

on_worker_boot do 
    ActiveSupport.on_load(:active_record) do 
    ActiveRecord::Base.establish_connection 
    end 
end 

before_fork do 
    ActiveRecord::Base.connection_pool.disconnect! 
end 
+0

什麼解釋說? http://guides.rubyonrails.org/active_record_querying.html#running-explain我們也可以看到您的遷移嗎? – emrahbasman

+0

你在說什麼移民?我將用解釋查詢來更新問題。 –

+0

你的地址表的模式。 – emrahbasman

回答

1

我會建議一些事情 - 兩種可能的解決方案,一種測試/再現n方法,並提供更深入度量的建議。

1)可能的快速解決方案:剝離1分鐘的作業,使其無阻塞。看看問題是否可以解決。嘗試使用Redis + Sidekiq,這很容易啓動和運行(或類似的東西)。

2)第二種可能的解決方案:查找對Postgres所做的任何完整表鎖或獨佔行鎖 - 查看您是否創建了全表鎖,如果是,請查找有問題的語句並將其刪除。

3)測試/複製:對於測試,看看您是否可以在生產之外複製此問題。我建議jmeter作爲一個非常有用的工具來模擬很多不同類型的請求和請求,並且看看你是否可以在受控/分段上下文中重現這一點。一致的複製是解決這類問題的關鍵。請參考生產服務器日誌,在發生問題的時間內生成您的jmeter測試請求,以便有助於重現問題。

如果你能想出辦法來複制它,然後你就可以開始調整模擬,看看是否刪除或增加/減少各種請求消除了該問題或改變某種方式的問題..

4) Analytics(分析):安裝NewRelic或類似的分析寶石,以更深入地瞭解該請求何時發生。您真的希望瞭解請求是否真正在Postgres中被阻止(通過獨佔行/表鎖阻止你的查詢),或者你是否由Puma執行隊列中的緩慢運行查詢備份,或者Ruby內部有某個不幸的等待狀態。

您還沒有足夠的信息來解決這個問題,因此您真的想要通過收集數據開始探索解決方案,以及對正在發生的事情的假設。

我對這類問題一般策略是(按順序):

  • 嘗試一些快速/易/安全修補程序(在盲),並查看是否有解決/改變。
  • 嘗試在非生產環境中進行復制(實際上,確實試圖完成此項工作)。
  • 儀器系統收集數據,看看你可以瞭解有關問題和任何相關的東西。
相關問題