ドキュメントに記載されている通常のresult()
方法では、すべてのレコードがすぐに読み込まれるようです。私のアプリケーションは約30,000行をロードする必要があり、一度に1行ずつ、サードパーティの検索インデックスAPIに送信します。明らかに、すべてを一度にメモリにロードすることはうまく機能しません(メモリが多すぎるためにエラーが発生します)。
だから私の質問は、ループで一度に1行をロードする従来のMySQLiAPIメソッドの効果をどのように達成できるかということです。
ドキュメントに記載されている通常のresult()
方法では、すべてのレコードがすぐに読み込まれるようです。私のアプリケーションは約30,000行をロードする必要があり、一度に1行ずつ、サードパーティの検索インデックスAPIに送信します。明らかに、すべてを一度にメモリにロードすることはうまく機能しません(メモリが多すぎるためにエラーが発生します)。
だから私の質問は、ループで一度に1行をロードする従来のMySQLiAPIメソッドの効果をどのように達成できるかということです。
これがあなたにできることです。
while ($row = $result->_fetch_object()) {
$data = array(
'id' => $row->id
'some_value' => $row->some_field_name
);
// send row data to whatever api
$this->send_data_to_api($data);
}
これは一度に1行を取得します。CodeIgniterのソースコードを確認すると、result()メソッドを実行したときにこれが実行されることがわかります。
大規模な結果セットでメモリを節約したい人のために:
CodeIgniter 3.0.0以降、unbuffered_row
関数があり、
上記のすべてのメソッドは、結果全体をメモリにロードします(プリフェッチ)。大きな結果セットを処理するには、unbuffered_row()を使用します。
このメソッドは、row()のように結果全体をメモリにプリフェッチせずに、単一の結果行を返します。クエリに複数の行がある場合は、現在の行を返し、内部データポインタを前方に移動します。
$query = $this->db->query("YOUR QUERY");
while ($row = $query->unbuffered_row())
{
echo $row->title;
echo $row->name;
echo $row->body;
}
オプションで、戻り値のタイプを指定するために、「object」(デフォルト)または「array」を渡すことができます。
$query->unbuffered_row(); // object
$query->unbuffered_row('object'); // object
$query->unbuffered_row('array'); // associative array
公式文書:https ://www.codeigniter.com/userguide3/database/results.html#id2
まあ、それresult()
はクエリの応答全体を与えるということです。row()
最初のケースをフェッチし、残りをダンプするだけです。ただし、クエリは、使用する関数に関係なく、30000行をフェッチできます。
あなたの目的に合う1つのデザインは次のようになります:
$offset = (int)@$_GET['offset'];
$query = $this-db->query("SELECT * FROM table LIMIT ?, 1", array($offset));
$row = $query->row();
if ($row) {
/* Run api with values */
redirect(current_url().'?offset'.($offset + 1));
}
これは1行を取り、それをapiに送信し、ページを更新して次の行を使用します。また、ページがタイムアウトするのを防ぎます。ただし、30 000のレコードと更新には時間がかかる可能性が高いため、ページロードごとに複数のAPIを使用しLIMIT ?, 1
て、より多くの数に調整することをお勧めします。1
result()
foreach()
さて、オブジェクトとして1つの行だけを返すrow()メソッド、または同じことを行うが配列を返すrow_array()メソッドがあります(もちろん)。
だからあなたは次のようなことをすることができます
$sql = "SELECT * FROM yourtable";
$resultSet = $this->db->query($sql);
$total = $resultSet->num_rows();
for($i=0;$i<$total;$i++) {
$row = $resultSet->row_array($i);
}
これにより、結果セット全体から各行がループでフェッチされます。これは、私が信じているメソッド呼び出しを
すべてフェッチしてループするのとほぼ同じです。$this->db->query($sql)->result()
一度に1行が必要な場合は、30.000回の呼び出しを行うか、すべての結果を選択して一度に1つずつフェッチするか、すべてをフェッチして配列をウォークオーバーします。今はどうしようもない。