【问题标题】:Rails caching not working for manual query?Rails缓存不适用于手动查询?
【发布时间】:2014-06-19 18:54:11
【问题描述】:

我正在尝试缓存我通过 SQL 查询获取的大量数据(100 000),但缓存不起作用(写入缓存大约需要 30 秒,读取它需要相同的时间)我做错了什么?我的配置变量已经设置为 true

    query = "SELECT inscriptions.`id`, banners.`id`, banners.`name`, inscriptions.`registered_at`, 
                inscriptions.`synched_at`, inscriptions.`state`
         FROM inscriptions
         JOIN firm_offices
         ON inscriptions.`firm_office_1_id` = firm_offices.`id`
         JOIN firms
         ON firm_offices.`firm_id` = firms.`id`
         JOIN banners 
         ON firms.`banner_id` = banners.`id`
         GROUP BY inscriptions.`id`"

result = ActiveRecord::Base.connection.execute(query)
Rails.cache.fetch 'huge-array' do
  data = []
  result.each do |r| 
    data.push({ :id => r[0],
                 :banner_id => r[1],
                 :banner_name => r[2],
                 :registered_at => r[3],
                 :synched_at => r[4],
                 :state => r[5]})
  end
  data
end
@data = Rails.cache.read("huge-array")

【问题讨论】:

  • 看来,由于您的查询周围没有条件,因此每次运行此函数时它都会运行。如果是这种情况,您就否定了缓存的用处。您是否尝试过为查询执行设置条件?
  • 你使用的是什么缓存存储?
  • @zoum26,你打算如何处理这些数据?似乎问题不在于查询或缓存本身,而在于实例化该大小的数组。您可能希望将数据分成几个可缓存的块(通过执行不同的 SQL 查询或将 data 拆分为一组,例如 10,000 个),但最好的方法取决于您的目标。跨度>

标签: ruby-on-rails ruby caching activesupport


【解决方案1】:

将其全部移动到您的 fetch 块中:

@data ||= Rails.cache.fetch 'huge-array' do
  query = "SELECT inscriptions.`id`, banners.`id`, banners.`name`, inscriptions.`registered_at`, inscriptions.`synched_at`, inscriptions.`state`
     FROM inscriptions
     JOIN firm_offices
     ON inscriptions.`firm_office_1_id` = firm_offices.`id`
     JOIN firms
     ON firm_offices.`firm_id` = firms.`id`
     JOIN banners 
     ON firms.`banner_id` = banners.`id`
     GROUP BY inscriptions.`id`"  
  result = ActiveRecord::Base.connection.execute(query)
  data = []
  result.each do |r| 
    data.push({ :id => r[0],
             :banner_id => r[1],
             :banner_name => r[2],
             :registered_at => r[3],
             :synched_at => r[4],
             :state => r[5]})
  end
  data
end

注意事项:

  • 您实际上不需要将所有这些都移到块中,只需将昂贵的部分(例如,execute(query))。
  • 您的大 SQL 查询看起来可以很容易地转换为 AR 查询。您可能希望将其转换为 AR 查询,然后使用 to_sql 如果结果证明效率更高。

【讨论】:

  • @zoum26,第一次需要很长时间,但后续请求应该会短得多。你的环境是什么?如果您在development 中运行,缓存将默认关闭。您需要在config/environments/development.rb 中设置config.action_controller.perform_caching = true(除非您已经这样做或正在生产中运行)。
  • 我正在开发中,config变量设置为true...我把rails logger放在我的代码中,即使有后续请求,当只需要读取缓存时,它就卡住了在阅读过程中持续 30 秒。 ://
  • @zoum26,正如 Frederick 上面所问的,您使用的是什么缓存存储?
  • 我真的不知道,我应该去哪里看?
  • 默认为memory_store。您需要确保它不是null_store。如果您使用的是 memcached 或类似的,您需要确保您的服务器正在运行。 config.cache_store 设置在 application.rbenvironments 文件中。
【解决方案2】:

无需在每次调用此函数时都运行查询和获取块。尝试类似

@data = Rails.cache.read("huge-array")

if @data.empty?
  result = ActiveRecord::Base.connection.execute(query)

  @data = []

  result.each do |r| 
    @data.push({ :id => r[0],
             :banner_id => r[1],
             :banner_name => r[2],
             :registered_at => r[3],
             :synched_at => r[4],
             :state => r[5]})
  end 

  Rails.cache.write("huge-array", @data)
end

return @data

这样你只需要在缓存中不存在数据的情况下进行昂贵的查询+数组创建。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-06
    • 2020-10-07
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多