- ベストアンサー
データベースから取得したデータを配列に格納(解決)
- データベースから取得したデータを配列に格納する方法について質問しています。解決方法として、pushと@workを使用する方法が紹介されています。
- 質問内容は、データベースからのレコードを配列に格納する方法についてです。解決方法として、pushと@workを使用する方法が示されています。
- 質問者はデータベースからのデータを配列に格納する方法を探しています。解決策として、pushと@workを使用する方法が提案されています。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは、 >******************************************* >◆[2]リファレンスを代入した場合 >for($i=0; $i<$sth->rows; $i++){ >@work = $sth->fetchrow_array; >$result[$i] = \@work; >} >※0.002~0.004秒(10件)0.4~0.5秒(50件) >******************************************* これの @result には期待した結果が得られなかったんじゃないですか? @result の各要素に格納されたのは全部同じ @work へのリファレンスになる気がします my @work = $sth->fetchrow_array; でレキシカル宣言すれば、それぞれ違う @work へのリファレンスになり期待した結果になると思います。 (検証してませんので違ったらすみません。) >もともと[3]のやり方は随所で「メモリーを大量に消費するので非推奨」 >******************************************* >◆[3]一度に全部のデータを取得した場合 >$ref = $sth->fetchall_arrayref; >@result = @$ref; >※0.002~0.004秒(10件)0.5~0.6秒(50件) >******************************************* 確かにこれはそうだと思い、(一応)とつけて書きました。 ですが、どの方法でも最終的に全てのデータを @result に格納するつもりなら、 結局メモリは使っちゃいますよね。 なら、 >@result = @$ref; こういった形でコピーせずに、取得したリファレンスを直接使えば、 fetchall_arrayref でも良いと思いますけど。 データの数を制限するなら、 SQLを書くときにそうなるように書くか(その方法は知りません) my @recs = (); while ( my $rec_ref = $sth->fetchrow_arrayref ){ push @recs , $rec_ref; last if scalar @recs > 100; } みたいにするかですかね >配列に格納すること自体をあまりしないのかもしれないですね。 まあ、表示するだけなら、配列にバッファしたりしないで、 一つずつ処理した方が良いのかも知れませんが、 そうもいかない場合もあるでしょうね、 まあ、大きいデータだと分かっているなら、 不用意にコピーせずに、リファレンスをうまく使うのが良いかもですね。 まあ、私は一般人(謙遜じゃありません)なので、参考程度で。
その他の回答 (2)
- g_p_
- ベストアンサー率53% (28/52)
こんにちは、 >完成度の高い解決方法 かどうかは?かも知れませんが。 なにしろ TMTOWTDI(There's more than one way to do it.) なのでいろいろですね、 速さについてはベンチマーク取ったりしないと分かりません。 ループで配列にフェッチなら、 my @recs = (); while ( my @rec = $sth->fetchrow_array ){ push @recs , \@rec; } もしくは配列のリファレンス my @recs = (); while ( my $rec_ref = $sth->fetchrow_arrayref ){ push @recs , $rec_ref; } 一応、一度に全部ってのもありますね。 my $array_ref = $sth->fetchall_arrayref; で、最初のヤツですけど、 >@result[$i] = ([$work[0],$work[1],$work[2],]); これは理解しにくいですね。 配列のスライスへ、無名配列へのリファレンスを一つリストとして代入ですかね? 分かっていてやっているならかまいませんけど。 @work をmyでレキシカル宣言しといて、 $result[$i] に @work へのリファレンスを代入すれば、 御希望の処理になったかも知れません。 for($i=0; $i<$cnt; $i++){ my @work = $sth->fetchrow_array; $result[$i] = \@work; } で、push にして、$i が必要なくなったなら、 while ( my @work = $sth->fetchrow_array ){ push @result, \@work; } の方が私は見やすいですね。 参考までに。
お礼
自分の記事を訂正できないようなのでこちらで失礼します。 実験で時間が掛かりすぎると思って調べたところブラウザの表示に時間を取られているようでした。再計測したら以下の通りでした。これだとどれを使っても許容範囲のような気もしますね。 ___10件____50件 [1]0.002~3____0.003~4 [2]0.002~3____0.003~5 [3]0.002~4____0.004~7
補足
回答ありがとうございます。 早速教えていただいたいくつかの方法で実験してみました。ネットワーク上のサーバでの実験なので、そのときの回線速度に影響されやすいですが、複数回数実験した平均値で計測してみました。(異常に高い数値は除外)取得データ10件の場合のページリクエストしてから表示されるまでの時間と50件の場合です。 ******************************************* ◆[1]pushで配列に格納した場合 for($i=0; $i<$sth->rows; $i++){ @work = $sth->fetchrow_array; push @result, [@work]; } ※0.002~0.004秒(10件)0.4~0.5秒(50件) ******************************************* ******************************************* ◆[2]リファレンスを代入した場合 for($i=0; $i<$sth->rows; $i++){ @work = $sth->fetchrow_array; $result[$i] = \@work; } ※0.002~0.004秒(10件)0.4~0.5秒(50件) ******************************************* ******************************************* ◆[3]一度に全部のデータを取得した場合 $ref = $sth->fetchall_arrayref; @result = @$ref; ※0.002~0.004秒(10件)0.5~0.6秒(50件) ******************************************* 実験の結果、[1]と[2]は殆ど差が出ませんでしたので、好みの問題かもしれません。ただ共通して言えることは、データ件数は5倍程度なのに、掛かった時間が100~200倍となっているので、大規模データを配列で運用するのは限界があるのかなと思います。 次に[3]の結果ですが、10件程度だと[1][2]との差はありませんが、50件になると250倍~300倍となってしまい、もともと[3]のやり方は随所で「メモリーを大量に消費するので非推奨」との記事が散見されたので実験はしていませんでしたが、実行速度の面においても厳しいのかなと思いました。 ちなみにperlだと一般的にどのやり方が主流なのでしょうか?もしかすると配列に格納すること自体をあまりしないのかもしれないですね。
- okg00
- ベストアンサー率39% (1322/3338)
記述したところで質問でない物は削除されますので無意味かつネット資源の無駄遣いという事で有害ですらあります。 日記ならチラシの裏にでもどうぞ。
補足
**************************** ※但し、実行速度などのパフォーマンスまでは実験していません。取得するレコード数が多くなった場合のパフォーマンスの低下など考慮が必要なことがあるかもしれませんし、もっと効率的なやり方があるかもしれません。もしより完成度の高い解決方法をご存知の方がおられましたら、後学のためにも回答をお願いいたします。 **************************** これが質問なのですが。読めませんか? だから質問の緊急度もちゃんと変えてあるでしょう。 逆に伺いたいのですが、貴殿の書き込みによって誰か得をする方でもおられますか?ネット資源の無駄遣いと言うのなら同じような質問が大量に出回って放置されている方がよりそうなのだと私は思いますけどね。特に技術系の質問は質問内容と結果が結びついて初めてネット資源として有効なのだと思いますが。 少なくとも貴殿のこの書き込みを見て喜ぶのは貴殿自身だけで、全く他を益さないということだけは理解した方が今後の貴殿自身のためだと思います。 まぁ、貴殿のような人物が私の目の前で堂々と同じことが言えるとはとても思えませんが、顔が見えないということで好き勝手ができる。ネットの弊害ですね。 ストレス発散のための書き込みならチラシの裏にでもどうぞ。
お礼
また前後してしまいました。 [2]はご指摘の通りmyが抜けてますね。ソースにはコメントで記述があるのでこちらへ書き込むときに消えたのだと思います。 [3]は、@$refのコピーを生成しているからその分単純に時間が掛かっているのですね。プログラムの構造上、取得したデータ全体の配列、若しくはデータの配列への参照が必要だったのですが、$sth->fetchrow_arrayrefで取得した$refの参照をreturnしてあげた方がパフォーマンス的によさそうですね。実際はSQLを発行する際にソートと絞り込みは行うのでそんなに膨大なデータにはならないと思います。 大分助かりました、ありがとうございました。