teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

ちょっと変更

2016/04/25 22:03

投稿

raccy
raccy

スコア21767

answer CHANGED
@@ -9,6 +9,6 @@
9
9
 
10
10
  each()の実装の仕方によります。each()が実装されているオブジェクトは大きく二種類あって、ArrayやHashのように何からのデータの集まり(コレクション)なものと、IOなどのデータの流れ(ストリーム)なものです。コレクションでのeach()は単純で、毎回上から順番に辿ることができます。しかし、ストリームでは、基本一度流れたものは(リセットしない限り)二度目は流れません。このような場合はeach()が使えるのは**一度だけ**になります。その代わり、ストリームはコレクションのように全てをメモリに展開する必要が無いため、メモリ消費量を抑えることができます。
11
11
 
12
- mysql2のeach()はlazy(遅延)処理であり、必要になって初めてsqlの結果からオブジェクトを生成するようで、上で言うストリームに近い処理です。ただ二回走らせることができるようにと、キャッシュを生成するようになっています。問題はそのキャッシュです。each()が完全に終わるまではキャッシュは中途半端な状態であり、そんなときにeach()が呼ばれたため、キャッシュ生成に不整合が発生しておかしくなったと思われます。なお、キャッシュを持たず一回だけを省メモリ高速にするの上で述べstreamのオプションでありこの場は完全にストリームとなって一度けになります。
12
+ mysql2のeach()はlazy(遅延)処理であり、必要になって初めてsqlの結果からオブジェクトを生成するようで、上で言うストリームに近い処理です。ただ二回走らせることができるようにと、キャッシュを生成するようになっています。問題はそのキャッシュです。each()が完全に終わるまではキャッシュは中途半端な状態であり、そんなときにeach()が呼ばれたため、キャッシュ生成に不整合が発生しておかしくなったと思われます。一度each()を呼び出した場合でうまくいったのはそのキャッシュが完全にできあため不整が発生しくなくなたからと思われます。
13
13
 
14
- mysql2配列と同じようにしたい場合にeachに`:as => :array`オプションが用意されているようです。こちらを使えば上のキャッシュ生成による不整合を防げると思われま全体的なメモリ消費量は多くなりますが、お試しください。
14
+ なお、キャッシュを持たずに一回だけを省メモリ高速にするのが上で述べたstreamのオプションであり、この場合は完全にストリームとなって一度だけになります。また、配列と同じようにしたい場合にeachに`:as => :array`オプションが用意されているようです。こちらを使うことでも、上のキャッシュ生成による不整合を防げるかもしれません

1

追加の質問への回答

2016/04/25 22:03

投稿

raccy
raccy

スコア21767

answer CHANGED
@@ -1,3 +1,14 @@
1
1
  queryでstreamオプションを有効にするとうまくいくかも知れません。
2
2
  [https://github.com/brianmario/mysql2#user-content-streaming](https://github.com/brianmario/mysql2#user-content-streaming)
3
- あとは、全体の物理メモリやスワップメモリの容量はどうでしょうか?膨大なメモリの予約を行う場合があり、スワップメモリがある程度ないとメモリ不足として弾かれる場合があるというのを聞いたことがあります。
3
+ あとは、全体の物理メモリやスワップメモリの容量はどうでしょうか?膨大なメモリの予約を行う場合があり、スワップメモリがある程度ないとメモリ不足として弾かれる場合があるというのを聞いたことがあります。
4
+
5
+ ---
6
+
7
+ > MySQLからの結果データセットをeach()で読み込んだ後、読み込み開始位置?が最後のレコードになっている状態で、再度each()を発行するとダメということでしょうか?そもそも根本的に結果データセットのeach()について自分が勘違いしているかも知れませんので、(動くようにはなりましたが)自己解決にはしないことにします。
8
+ どなたか詳しい方、ご教授お願い致します。
9
+
10
+ each()の実装の仕方によります。each()が実装されているオブジェクトは大きく二種類あって、ArrayやHashのように何からのデータの集まり(コレクション)なものと、IOなどのデータの流れ(ストリーム)なものです。コレクションでのeach()は単純で、毎回上から順番に辿ることができます。しかし、ストリームでは、基本一度流れたものは(リセットしない限り)二度目は流れません。このような場合はeach()が使えるのは**一度だけ**になります。その代わり、ストリームはコレクションのように全てをメモリに展開する必要が無いため、メモリ消費量を抑えることができます。
11
+
12
+ mysql2のeach()はlazy(遅延)処理であり、必要になって初めてsqlの結果からオブジェクトを生成するようで、上で言うストリームに近い処理です。ただ二回走らせることができるようにと、キャッシュを生成するようになっています。問題はそのキャッシュです。each()が完全に終わるまではキャッシュは中途半端な状態であり、そんなときにeach()が呼ばれたため、キャッシュ生成に不整合が発生しておかしくなったと思われます。なお、キャッシュを持たずに一回だけを省メモリで高速にするのが上で述べたstreamのオプションであり、この場合は完全にストリームとなって一度だけになります。
13
+
14
+ mysql2でも配列と同じようにしたい場合にeachに`:as => :array`オプションが用意されているようです。こちらを使えば上のキャッシュ生成による不整合を防げると思われます。全体的なメモリ消費量は多くなりますが、お試しください。