DBへのアクセスについて - PHPプロ!Q&A掲示板

150

  • 0P

DBへのアクセスについて

質問日時 / 2006年8月29日 13:53    回答数 / 7件

Questioner:  marukome  このエントリーをはてなブックマークに追加 

キーワード / セキュリティ    速度   

検索結果を求めたい(必要な情報が入っているテーブル5つとします)時がありますよね?

そのときにみんなJOINで結合するのとメインのテーブルのデーターを取得しそのデーターをキーとして他のテーブルからデータを取ってくる(例えば全部で5回sql文を掛けるとする)のはどちらがいいのでしょうか?速さやセキュリティ上の問題などあるのでしょうか?

私的にはテーブルを5つも結合するとsql文がきたなくなったりするのが嫌いだったりするんですけど。 よろしくお願いします

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┣A01shizk結合してアクセスしたほうが圧倒的に速いです。例えば
┃┗A01-1marukome丁寧なお返事ありがとうございます。 やっぱり結合
┣A02kashiphpJOINによるオーバーヘッドよりも普通はSELECTがたくさ
┃┗A02-1marukome丁寧なお返事ありがとうございます。 explain関数
┣A03galluがると申します。 んっと…実測値ではないのですが。
┃┗A03-1marukome丁寧なお返事ありがとうございます。 今までのお返
┗A04shizk> あと一つ質問してもよろしいですか?phpには配列の

回答一覧

並び替え:

A01 満足
answerershizk [8月30日 10:27]

結合してアクセスしたほうが圧倒的に速いです。例えば、2つのテーブルへ別々にアクセスすると3倍ほど時間がかかることがあります(余分なスクリプト部分も加えて)。

確かに、コードが見にくくなりますから、速さを重視しないのであれば好みの問題かもしれません。しかし、取り出すデータ量が増えるほど、その差は顕著になります。ですので、できるなら結合に慣れていった方が良いかと思います。

この意見に回答する

ツリーへ TOPへ

A01-1
replyermarukome [8月30日 15:31]

丁寧なお返事ありがとうございます。

やっぱり結合して取った方が早いんですね。でも3倍ぐらい時間が掛かったりするときがあるのはびっくりしました。確かにテスト段階や社内のシステムじゃないかぎり結合の方向で行こうと思います。(そうじゃなくてもしなきゃいけないんですけど・・)

あと一つ質問してもよろしいですか?phpには配列の数を取得するcount関数がありますがDBからデーターの件数を取得する場合は上記(アクセスが遅くなる)ことも考えるとcount関数の方の方がよろしいんでしょか?それともSQL文でCOUNT(*)を使った方がよろしいのでしょうか?(私は今までSQLの方で取得していたので…) ペーチングする時は別ですけど…(ペーチング以外で使うときは滅多にないと思いますけど。)よろしくお願いします。

この意見に回答する

ツリーへ TOPへ

A02 満足
answererkashiphp [8月30日 12:55]

JOINによるオーバーヘッドよりも普通はSELECTがたくさんある方が一般的には遅いです。
データ件数によっては問題にならないケースもあるでしょうが、そのメインテーブルのレコード数が当初は5件だったので5回のSQLで済んでいたのが100件になり100回のSQLが必要になったりして運用していくにつれてパフォーマンスが劣化していくというのはよくある話です。
SQLの発行回数が固定であるならexplain等をして5回のつみあげと1回のときとでの処理時間を見積もってみると実感をもてるんではないでしょうか?

この意見に回答する

ツリーへ TOPへ

A02-1
replyermarukome [8月30日 15:47]

丁寧なお返事ありがとうございます。

explain関数を調べてみて等しらべたりしてみた所1.5倍から3倍くらいまで違ったりしました。カラム数やインデックスによって違ってきたりもするんですね(当たり前ですけど…)これからはテーブルを結合するように致したいと思います。

先ほどの人にも質問致した所なんですけどphpにcount関数がありますがデーターの件数を取得するばあいは取ってきたデーターに対してcount関数をかけてあげるのとSQL文でCOUNT(*)件数をあげるのはどちらがよろしいでしょうか?返信を見る限りphp側の方を使ってあげた方がいいと思いますけど今まではSQL文の方でやってきたので… よろしければお願いします。

この意見に回答する

ツリーへ TOPへ

A03 満足
answerergallu [8月30日 16:05]

がると申します。
んっと…実測値ではないのですが。速度から考えると、恐らく「適切に記述した一本のSQL」のほうが速度は出るだろうと思われます。
で、それを踏まえたうえで。私なら「別々にSQLを発行する実装」を選択します。
理由は概ね保守性の確保でしょうか。複雑なSQLは、一つには「DBMSに固有になりやすい」部分が多く、それだけでも面倒が多くなりやすいですし。
その他諸々あって、そのあたりは「速度をある程度犠牲にしてでもわかりやすいものをつくる」ようにしています。

ただまぁ後は「致命的なくらい遅い」のであれば、その部分だけ厳重に囲い込んだ上で、飽く迄例外として「汚いけど早い」クラスを切っておくってのも一つの方向性だとは思うのですが。
そのあたりは現場の状況におけるバランス感覚かと思います。

この意見に回答する

ツリーへ TOPへ

A03-1
replyermarukome [8月30日 18:31]

丁寧なお返事ありがとうございます。

今までのお返事の結果結合する部分は結合する(コードが汚くならない程度)、データを自分の思う形で取りたいときは別々に実装という結論に至りました。

でも一つ一つ検索を掛けてやると最終的にSQL側でソートができなかったり(phpのusort関数を使用)したりするとやっぱり遅くなりますね。

クラスを作成するのは少し難しいのですね…

この意見に回答する

ツリーへ TOPへ

A04
answerershizk [8月30日 23:43]

> あと一つ質問してもよろしいですか?phpには配列の数を取得するcount関数が
> ありますがDBからデーターの件数を取得する場合は上記(アクセスが遅くなる)
> ことも考えるとcount関数の方の方がよろしいんでしょか?
> それともSQL文でCOUNT(*)を使った方がよろしい> のでしょうか?
> (私は今までSQLの方で取得していたので…)ペーチングする時は別ですけど…
> (ペーチング以外で使うときは滅多にないと思いますけど。)
> よろしくお願いします。

COUNT(*)で件数を取得する場合は1回で1つの結果を取得するので気にする必要はないと思います。また、単にレコード数を調べるだけなら、わざわざ全データを取得してcount関数を使う方がリソースを余分に使う可能性もあります。
先の回答では字足らずでした。例えば、10000件程度のレコードを扱う場合にはJOINを使って結合した方が圧倒的に速いです。しかし、20、30件程度のレコードを扱うのであれば、1つのテーブルへSELECTを用いて結果を求め、それを使って次のデータを取り出す方法でも十分問題ありません。ロジック部分をスッキリさせるには適しているのではないでしょうか。要は使いどころを覚えることが重要だと思います。

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
array_mergeの再帰処理の動作について
 このエントリーをはてなブックマークに追加 
A
>1個になったとき$leftを返しますが、 >このとき、最終的な$leftはnullになるかと思います。 いいえ、最後は「渡された配列をそのまま」返します。要素が2以上あるときとの違いは(並べ替えずに戻るので...

>>続きを読む

再帰関数は最初の内は混乱しますが、非常に上手く使える場面もいずれ出てきます。これを機会に学んでいけるといいですね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)