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')
また、特定の組織への出張などが必要な場合は、オプションで他の条件を追加します。
NB私は可能であればページネーションを避けたいと思います。
私の考え:私の想像では、これは「カーソル」のように機能するはずです。次のようなものを格納するのではなく、クエリを作成します。ループで必要になるたびに@trips_cursor = myquery
、ビューでモデルオブジェクトが作成されます(破棄されます)。trips_cursor.each_row do |trip|
明らかに読み取り専用にすることができます。
PHPではなくRubyonRailsコードが必要です
回答の更新
その間に何かを学んだので、見つけた情報を共有したいと思います。まず、ARクエリ(ここで、結合、制限、およびいくつかの同様のメソッド)を使用する場合、 ARメソッドではないクエリでメソッドを実行するまで、クエリは実行されません(遅延読み込み) 。基本的に、すべてのメソッドがクエリを実行します。そのため、実行されていないARクエリでを実行すると、メモリ内の1つの行のみが読み込まれ、毎回それが出力され、貴重なRAMが保持されます。このアプローチを使用したのは、巨大な結合のおかげで、必要なものがすべて読み込まれ、すべてのレコードが一意であるため、キャッシュする必要がないためです。each
find_each(batch_size: 1)