在 PHP(过去)中,您曾经mysql_fetch_assoc
在 html 上逐行打印一些内容。基本上,你正在对一些 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')
如果我需要,我可以选择添加其他条件,例如,为特定组织旅行。
注意如果可能的话,我想避免分页。
我的想法:在我的想象中,这应该像“光标”一样工作,我进行查询,而不是存储类似的东西@trips_cursor = myquery
,然后在视图trips_cursor.each_row do |trip|
中创建一个模型对象(并丢弃它)每次都需要循环。它显然可以是只读的。
我需要 ruby on rails 代码,而不是 PHP
更新答案
由于我同时学到了一些东西,所以我想分享一些我发现的信息。首先,如果您使用 AR 查询(where、joins、limit 和一些类似的方法),查询将不会运行(延迟加载),直到您在查询上运行一个方法,这不是AR 方法。基本上每个each
方法都会触发查询。因此,如果您find_each(batch_size: 1)
在未触发的 AR 查询上执行 ,它只会在内存中加载一行并每次打印出来,从而保留您宝贵的 RAM。请注意,我使用这种方法只是因为,由于我的巨型连接,我加载了所需的所有内容并且所有记录都是唯一的,因此我不需要缓存它们。