以HTML格式逐行打印SQL结果而不在内存中存储所有行

时间:2013-01-25 17:29:47

标签: ruby-on-rails ruby-on-rails-3.2

在PHP(过去)中,您使用mysql_fetch_assoc逐行打印html上的内容。 基本上,tou正在对某些sql结果进行循环,而不将整个结果存储在内存中。

我有一种情况,当我正在进行一个非常大的查询时,它“加入”所有必需的表来形成一个大行,所以当我请求例如一个关联的模型时,查询不会调用数据库,因为数据被视为“缓存”。

这个查询的最大问题是,它是巨大的,它将很多东西加载到内存中。 因为是使用连接构建的,所以我真的不需要在内存中一次加载所有使用过的表的所有数据,因为每一行都可以直接打印(感谢这个连接),所以我的想法基本上是在每个获取的行上创建一个循环并直接打印,然后丢弃。

我怎样才能实现这样的目标?

这是我正在使用的粗略表结构(未完成):

Trips
  - has_many Hikers
  - belongs_to Organization

Hikers
  - belongs_to PersonalRecord

PersonalRecord

Organization
  - has_many Trips

我的加入只需要进行所有旅行,并将此表的每一行加入组织,徒步旅行者和个人记录。

更新1:

目前我正在使用此查询来获取结果:

table_join_to_cache = '
  INNER JOIN organizations    ON organizations.id         = trips.organization_id
   LEFT JOIN cities           ON cities.id                = trips.city_id
   LEFT JOIN hiker_trips      ON hiker_trips.trip_id      = trips.id
   LEFT JOIN hikers           ON hikers.id                = hiker_trips.hiker_id
   LEFT JOIN personal_records ON personal_records.id      = hikers.personal_record_id
   LEFT JOIN trip_trip_levels ON trip_trip_levels.trip_id = trips.id
   LEFT JOIN trip_levels      ON trip_levels.id           = trip_trip_levels.trip_level_id
'
@trips = Trip.joins(table_join_to_cache)
             .where('trips.begin_date >= ? AND trips.begin_date <= ?', begin_of_month, end_of_month)
             .uniq.order('begin_date ASC, title ASC')

如果我需要例如特定组织的旅行,我可以选择添加其他条件。

N.B。如果可能,我想避免分页。

我的想法:在我的想象中,这应该像“光标”一样,我进行查询,而不是像@trips_cursor = myquery那样存储,然后在视图trips_cursor.each_row do |trip|中每次循环时都需要创建一个模型对象(并丢弃它)。它可以是非常简单的。

我需要ruby on rails代码,而不是PHP

更新回答

由于我已经学到了一些东西,我想分享一些我发现的信息。 首先,如果你使用AR查询(where,join,limit和一些类似的方法),查询将不会运行(延迟加载),直到你在查询上运行一个方法,这不是一个 AR方法。基本上每个each方法都会触发查询。如果您执行find_each(batch_size: 1),在未被触发的AR查询上,它将只在内存中加载一行并每次打印出来,保留您宝贵的RAM。请注意,我使用这种方法只是因为,由于我的巨大连接,我加载了所需的一切,所有记录都是唯一的,所以我不要求它们被缓存。

3 个答案:

答案 0 :(得分:1)

检查此链接:

http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects-in-batches

我认为你所要求的是find_each方法。默认情况下,一次加载1000行可能没问题,但您可以将其配置为获取更少或更多。

我希望有所帮助。

答案 1 :(得分:1)

使用find_each或find_in_batches的示例(可能更好)如果@trips是视图中的关系:

<%= @trips.find_in_batches do |trips| %>
  <%= render partial: trips %>
<% end %>

那是怎么回事?

另外,如果结果非常大,我强烈建议您考虑使用某种形式的缓存,如ActiveSupport :: Cache :: Store:http://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-store

答案 2 :(得分:0)

我确信有很多聪明的解决方案,但为什么不在SQL查询中使用好的旧LIMIT?只需获取500行即可处理它们并获取更多信息。