2011-08-18 69 views
0

我现在有这样的代码:优化内存密集型脚本

shop_category.shop_sub_categories.each do |sub_category| 
    products << sub_category.products 
    end 

    products = products.flatten.uniq.compact 


    data = products.first(100).map do |product| 
    { 
     :name => CGI.unescapeHTML(product.name), 
     :manufacturer => product.manufacturer, 
     :detail => product.description, 
     :sales_rank => product.sales_rank, 
     :price => product.price, 
     :retailer => product.retailer 
    } 
    end 

我发现这非常内存密集型,因为它使用了我的CPU的96%:

shop_category.shop_sub_categories.each do |sub_category| 
    products << sub_category.products 
    end 

我想到的写一些符合WHERE IN语句的东西,以便我可能只查询像这样的数据:

SELECT * FROM products JOIN shop_categorization ON product_id = products.id WHERE shop_sub_category_ id IN(1,2,3,4,5)

我目前把这个脚本放在了很棒的地方。我正在考虑是否有什么可以做的更多Rails-y。

sub_category_ids = shop_category.shop_sub_categories.map(&:id) 
    sub_category_ids = sub_category_ids.join(',') 
    products = Product.find_by_sql("SELECT * FROM products JOIN shop_sub_categorizations ON product_id = products.id WHERE shop_sub_categorizations.shop_sub_category_id IN (#{sub_category_ids}) LIMIT 100") 
+1

它是内存还是CPU密集型? –

+0

CPU密集型。对不起 –

回答

1

如果你只是想子类别ID代替,:

sub_category_ids = shop_category.shop_sub_categories.map(&:id) 

您可以改为仅选择ID列:

sub_category_ids = shop_category.shop_sub_categories.select('id').map(&:id) 

此外,重建你的find_by_sql声明使用ActiveRecord方法进行工作,您可以执行以下操作:

products = Product.join("JOIN shop_sub_categorizations ON product_id = products.id").where(["shop_sub_categorizations.shop_sub_category_id IN (?)", sub_category_ids]).limit(100) 

请记住,通过不指定要选择的列,您将增加选择回所有列并将它们映射到内存中的计算开销。

编辑:

查看进程监视器来确定您的开销是Ruby脚本,或数据库。将索引添加到数据库可能会减少数据库查询的CPU开销。有关SQL索引的更多信息,请访问:http://www.w3schools.com/sql/sql_create_index.asp

+0

关于'不选择列',当然我选择列。我只是没有把它。 –