PHP & MySQL


MySQLを使った掲示板を作成しています。

index.php ではまず20件ずつ各トピックス名や前トピック数、最終更新時間、未回答件数などを表示しています。しかし表示する物が多く一度に異なったSQLを5~6ほどはいて検索させ、表示しています。

また、各トピックの表示はindex.phpではなく topic.phpに任せているのですが、ここでも数個のSQLがあります。

---
$sql = "select * from `bbs` ....
$res = mysql_query($sql,$connection);

$sql2 = "select `name` from....
な感じです。

しかし、index.phpとtopic.phpを何回も早い感じでリンクを進んだり戻ったりしていると急に表示されなくなり、更新しても表示されません。そして数分後、再度更新すると普通に表示されます。

たぶんSQLなどを大量にはいたり、組み方が下手なせいだと思いますが、なにかいい改善方法などないでしょうか?よろしくお願いします。

PS:phpbbなどを使えばいいなどの回等は不要です。またあまりオブジェクト指向に関しては理解していません。

回答の条件
  • 1人5回まで
  • 登録:2006/07/19 17:00:20
  • 終了:2006/07/25 21:30:08

ベストアンサー

id:bonlife No.5

回答回数421ベストアンサー獲得回数752006/07/20 01:06:51

ポイント40pt

SQLの列名などから想像するに

  1. incrementされるnewidの降順 (新しい発言の取得?)
  2. 日付指定
  3. 特定のキーワードを含むもの
  4. 公開設定による絞込み (public)

といったような5つの検索を行っているように思えるのですが、1つのページにはどのような情報を掲載しているのでしょうか。

全て1つのページのためのSQLだとしたら、何か問題があるような気がします。

複数のテーブルから色々な情報を取得しており、それぞれが独立した情報の場合、SQLが多くなるのは仕方ありませんが、全て同じテーブルを対象にしていますよね。

普通、1回か2回のSQL文でなんとかなるはずです。

表示画面のイメージがもう少し明らかになるとより的確な回答がつくのではないかと思います。

また、質問文中に「20件ずつ」表示している、という記述がありましたが、この20件というのはどのように指定していますか。

上記のSQLにはLIMITやOFFSETによる指定がないようでしたので、このままでは全件データを取得してしまいます。

もし現時点でLIMITを使っていないのであれば、LIMITを使うだけで大幅に改善すると思います。

LIMIT 節を使用すると、SELECT ステートメントで返されるレコード数を制限することができる。LIMIT は 1 つまたは 2 つの数値引数を取る。これらの引数は整数定数でなければならない。

[参考URL]

また、最後のチューニングの部分になりますが、SQLのSELECTにてWHERE句で指定する列についてはINDEXを張っておくと検索速度が著しく向上します。

他にはSELECTで選択する列をアスタリスク(*)指定せずに、本当に必要な列だけに限定することで、いくらか速度は向上すると思います。

参考になれば幸いです。

id:esecua

bonlifeさん、いつもありがとうございます。

2006/07/25 21:28:31

その他の回答(4件)

id:ito-yu No.1

ito-yu回答回数323ベストアンサー獲得回数142006/07/19 17:24:02

ポイント10pt

それはMySQLの同時接続数制限に引っかかっているに違いありません

http://www.y2sunlight.com/ground/?MySQL4.1%2F3.MySQL%A5%B5%A1%BC...

SQLをもっと整理して、一画面表示するのに2~3回のクエリで済むような設計にするのが一番良いと思うのですが、ソースを見ないことには具体的なアドバイスは難しいですね。

phpbbを使え、とは言いませんが、phpbbのソースを見て勉強してみてはいかが?w

id:esecua

回答ありがとうございます。

もしよろしければ「SQLをもっと整理して、一画面表示するのに2~3回のクエリで済むような設計にするのが一番良い」に関して再度アドバイスお願いします。

ソースですが全て載せれないのでSQL周りを載せます。

if (!$conn = mysql_connect($host, $user, $password)){die("接続できません");}

mysql_select_db($name, $connection);

$sql = "SELECT * FROM `bbs` WHERE `new` = '".$newid."' ORDER BY `number` DESC";

$res = mysql_query($sql,$connection);

$sql2 = "SELECT * FROM `bbs` WHERE `day` = '".$dayid."';";

$res2 = mysql_query($sql2,$connection);

$sql3 = "SELECT * FROM `bbs` WHERE `keyword` = '".$word."' AND `$id->check` = 'OK';";

$res3 = mysql_query($sql3,$connection);

$sql4 = "SELECT * FROM `bbs` WHERE `public` = '".$publicid."';";

$res4 = mysql_query($sql4,$connection);

$row4 = mysql_fetch_object($connection);

こんな感じでたくさんのSQLを吐いています。一部ADOBDも使用して接続、検索しています。

これを接続制限に引っかからないように整理する方法を伝授願います。

2006/07/19 19:21:26
id:pxb12663 No.2

pxb12663回答回数395ベストアンサー獲得回数142006/07/19 19:10:36

ポイント15pt

肝心のソースがないので、具体的に何がやりたいのかよくわかりませんが、SQL構文のINNER JOINやLEFT JOINを活用すればスッキリしそうな気がします。

テーブルの結合ですね。リレーショナルDBならではの機能です。

http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/mysql_09.htm

ここを参考に頑張ってみてください。難しそうですが、慣れればたいしたことないです。

id:ito-yu No.3

ito-yu回答回数323ベストアンサー獲得回数142006/07/19 21:56:23

ポイント7pt

では再回答を。長いSQLですが

$sql = "SELECT 'NEW' AS rectype,* FROM bbs WHERE new = '{$newid}' UNION SELECT 'DAY' AS rectype,* FROM bbs WHERE day = '{$dayid}' UNION SELECT 'KWD' AS rectype,* FROM bbs WHERE keyword = '{$word}' AND {$id->check} = 'OK' UNION SELECT 'PUB' AS rectype,* FROM bbs WHERE public = '{$publicid}' ORDER BY type,number DESC";

とか、複数のSELECT結果をUNIONして取得します。rectypeていうカラムでそれぞれのレコードがどの条件なのかわかります。

ちなみにMySQLってバッククォート必須なんですか?無くてもいけると思って消しちゃいましたのでこのままではエラーになるかも。です。

id:esecua

ん?でもちょっとまてくださいよ。1個のSQLで叩いたとしてもデータと取得はどのように行うんですか? たとえば array['topic'] とした場合全てのSQLでの結果でのtopicカラムが表示されてしまいそうな感じがしますが。

あと、SQLですがなぜかエラーがでます。

2006/07/19 22:32:50
id:falcosapiens No.4

falcosapiens回答回数126ベストアンサー獲得回数132006/07/19 22:00:51

ポイント28pt

$res = mysql_query($sql,$connection);

(毎回link identifierを指定している)

を繰り返しているために毎回接続を開いていますね。

各スクリプトの最初の1度目を除いて

$connectionを削ってみると良いかと思います。

$res = mysql_query($sql);

という感じで。

http://php.s3.to/man/function.mysql-query.html

id:esecua

なるほど

2006/07/19 22:32:58
id:bonlife No.5

回答回数421ベストアンサー獲得回数752006/07/20 01:06:51ここでベストアンサー

ポイント40pt

SQLの列名などから想像するに

  1. incrementされるnewidの降順 (新しい発言の取得?)
  2. 日付指定
  3. 特定のキーワードを含むもの
  4. 公開設定による絞込み (public)

といったような5つの検索を行っているように思えるのですが、1つのページにはどのような情報を掲載しているのでしょうか。

全て1つのページのためのSQLだとしたら、何か問題があるような気がします。

複数のテーブルから色々な情報を取得しており、それぞれが独立した情報の場合、SQLが多くなるのは仕方ありませんが、全て同じテーブルを対象にしていますよね。

普通、1回か2回のSQL文でなんとかなるはずです。

表示画面のイメージがもう少し明らかになるとより的確な回答がつくのではないかと思います。

また、質問文中に「20件ずつ」表示している、という記述がありましたが、この20件というのはどのように指定していますか。

上記のSQLにはLIMITやOFFSETによる指定がないようでしたので、このままでは全件データを取得してしまいます。

もし現時点でLIMITを使っていないのであれば、LIMITを使うだけで大幅に改善すると思います。

LIMIT 節を使用すると、SELECT ステートメントで返されるレコード数を制限することができる。LIMIT は 1 つまたは 2 つの数値引数を取る。これらの引数は整数定数でなければならない。

[参考URL]

また、最後のチューニングの部分になりますが、SQLのSELECTにてWHERE句で指定する列についてはINDEXを張っておくと検索速度が著しく向上します。

他にはSELECTで選択する列をアスタリスク(*)指定せずに、本当に必要な列だけに限定することで、いくらか速度は向上すると思います。

参考になれば幸いです。

id:esecua

bonlifeさん、いつもありがとうございます。

2006/07/25 21:28:31

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません