【发布时间】:2014-06-02 15:20:07
【问题描述】:
环境:Ruby 2.0.0、Rails 4.0.3、Windows 8.1、PostreSQL、Datatable 1.12.2、Will_Paginate 3.0.5,都在运行服务器和客户端的开发高端笔记本电脑上。请注意,原来的问题已被删除并替换为此问题,以直接解决问题的原因。
当我为数据库播种以模拟满负载时,我的应用程序的索引操作出现性能问题。问题似乎是它读取了整个模型数据库,然后读取了显示索引所需的记录。
控制器代码导致此问题。在这种情况下,它与 Railscast 340 不同。我添加了导致问题的行,因为没有它我会出错。显然,这个补丁是错误的。控制器代码实际上在respond_to 之前发出对记录集的读取。这在 Railscast 340 中没有显示,但在 respond_to documentation 中显示。没有它,我会在视图中收到错误。控制器代码为:
def index
@products = Product.all # This line seems to be the problem, but errors occur without it.
respond_to do |format|
format.html
format.json { render json: ProductsDatatable.new(view_context) }
end
end
当@products = Product.all 不在控制器索引操作中时,每个在 nil 上接收 nomethoderror 的视图段是:
<% @products.each do |product| %>
在示例运行中,如下所示,第一个序列大约需要 3.4 秒,第二个序列大约需要 0.1 秒。此示例仅在我的开发系统上,这是一台同时运行服务器和客户端的高端笔记本电脑。但是,我非常担心即使分发到生产环境中,这种设计也无法扩展。
第一次读取和完成是:
SELECT "products".* FROM "products" WHERE "products"."company_id" = 54
…
Completed 200 OK in 3393ms (Views: 2851.6ms | ActiveRecord: 418.3ms)
下面的读取和补全是:
SELECT "products".* FROM "products" WHERE "products"."company_id" = 54 ORDER BY stock_number asc LIMIT 10 OFFSET 0
…
Completed 200 OK in 103ms (Views: 71.0ms | ActiveRecord: 26.0ms)
编辑添加解释分析
有趣的区别在于第一个查询没有显示索引,但架构显示产品是由公司索引的?
第一个查询:
"Seq Scan on products (cost=0.00..12.65 rows=234 width=51) (actual time=0.036..0.114 rows=234 loops=1)"
" Filter: (company_id = 54)"
" Rows Removed by Filter: 218"
"Total runtime: 0.153 ms"
第二次查询:
"Limit (cost=0.27..6.76 rows=10 width=51) (actual time=0.015..0.036 rows=10 loops=1)"
" -> Index Scan using index_products_on_stock_number on products (cost=0.27..152.07 rows=234 width=51) (actual time=0.014..0.033 rows=10 loops=1)"
" Filter: (company_id = 54)"
" Rows Removed by Filter: 14"
"Total runtime: 0.063 ms"
【问题讨论】:
-
能否向我们展示这两个查询的 EXPLAIN ANALYZE 的结果?
-
你好像忘记加分页了
Product.all.paginate(page: params[:page], per_page: 20) -
@FrankHeikens。我很高兴,但我得到一个 nomethoderror 试图运行解释。 AR Query Guide 说:“您可以对由关系触发的查询运行 EXPLAIN。”这是直接查询,而不是关系。这就是它失败的原因吗?你能告诉我在这种情况下如何运行它吗?谢谢...
-
@edaried。 Railscast 340 将分页留给 ProductsDatatable 类。例如,我试图限制使用 .first(50) 查询传递的记录。第一个视图仅显示 50 条记录,但随后的视图已更正。这不是最佳解决方案。想法?谢谢...
-
您可以使用 psql、pgAdmin 或任何您喜欢的 PostgreSQL 客户端在您的数据库上运行查询:EXPLAIN ANALYZE SELECT _rest_of_your_sql;
标签: ruby-on-rails ajax postgresql datatables will-paginate