test79824007 2013-02-13 08:30:45

[PHP] 1回の検索で14000回のSQLを発行する検索画面 このエントリーをはてなブックマークに追加

投稿者からのアピールポイント

開発してから徐々に遅くなってきたので何とかして欲しいと頼まれました。

調べてみると、毎回14000回ほどのSQLが発行され、 検索するたびにサーバーを攻撃しているような状態になっていました。

修正してみたらSQL発行は1回で済み、劇的に速くなってビックリされました。

ちなみに、検索画面とCSV出力で同じ処理が使用されており、 CSV出力は一度検索を行わないとボタンが表示されません。

// ★全件検索
$select = "SELECT * FROM hoge1 left join hoge2 on hoge1.a_id=hoge2.a_id";

$result = mysql_query($select);

while($row = mysql_fetch_array($result)) {

	// ★出力内容格納用
	$linestr ="";
	// ★データ統合用
	$data = array();
	foreach($row as $name => $value) {
		$data[$name]=$value;
	}

	// ★全件検索の結果で別のテーブル検索
	$select2 = "select * from hoge3 where b_id = " . $row["b_id"];
	$result2 = mysql_query($select2);
	// ★$dataに統合

	// ★全件検索の結果で別のテーブル検索
	$select3 = "select * from hoge4 where b_id = " . $row["b_id"];
	$result3 = mysql_query($select3);
	// ★$dataに統合

	// ★全件検索の結果で別のテーブル検索
	// ★上と同じテーブルだが条件を追加している
	$select4 = "select * from hoge4 where b_id = " . $row["b_id"]
		. " and c='xxx'";
	$result4 = mysql_query($select4);
	// ★$dataに統合

	// ★出力内容作成
	$linestr .= "<tr><td nowrap>".$my_id.'&#160;</td><td nowrap>';
	$linestr .= $data["xx"].'&#160;</td><td nowrap>';
	$linestr .= '&#160;</td><td nowrap>'; 
	// ★省略

	////////////フィルタ関連//////////////
	if(
	//○フィルタ
	(条件) 
	//△フィルタ
	&& 
	(条件)
	//□フィルタ
	&& 
	(条件)
	//●フィルタ
	&& 
	(条件)
	//▲フィルタ
	&& 
	(条件)
	//■nullチェック nullではないときのみ表示
	&& 
	($data["xxx"]!='')
	){
	$output .= $linestr; //すべてtrueなら表示文字列にレコード追加
	}
	/////////////////////////////////
}

// ★CSVの場合
if($_GET['csv']==1){
	// ★HTMLタグとか除去
	$output = str_replace("&#160;","",$output);
	$output = str_replace("<table border=1>","",$output);
	$output = str_replace("<th nowrap>",'"',$output);
	$output = str_replace("</th>",'",',$output);
	$output = str_replace("\r\n",'',$output);
	$output = str_replace(",</tr><tr><td nowrap>","\r\n".'"',$output);
	$output = str_replace("<tr>",'',$output);
	$output = str_replace("</tr>","\r\n",$output);
	$output = str_replace("<td nowrap>",'"',$output);
	$output = str_replace("</td>",'",',$output);
	// ★CSV出力
}else{
	// ★画面出力
}

コメント(6)

#1 okadabasso 2013-02-16 09:24:39  

このコードが途中の省略以外変更されてないとするとすごく怖い。「社内システムだから悪意はない」って言う前提は破棄したほうがいいと思うよ。

#2 m_shige1979 2013-02-18 04:00:46  

当時、外部結合を知らなかった頃にこんなことをしたことがある

#3 math_neko 2013-05-13 12:23:33  

14000 回…ゴクリ

#4 elseorand 2015-07-02 07:28:48  

MySQLならgroup_concatとかで、N+1問題回避できるだろうに。 それ以前にJOINを知らないレベル? また、PreparedStatementを使用すべき

#5 tanaharumize 2017-02-13 08:38:29  

これ外部開発会社がやってきたから修正依頼出したら別途料金とかいわれたよ。まじくそ。 ループ内で平気でクエリ投げるやつって何なの。

#6 migimatsu 2017-02-13 08:46:48  

個別クエリは当然クソだが、そもそもなんでループ内に書こうと思った、、、


このウンコードに臭った人は、こちらのウンコードにも臭ってます

[その他] HOW TO ABC..

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

実際にあった某システムの超重要なマスター...

create table item_master (
 A varchar(2...

鑑賞する »

[PHP] つ、釣り!?

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

ツボって思い出し笑いが止まらなかったので...

class Hoge {
    /*
      * インストラクター
...

鑑賞する »

[Java] 連番

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

もはや人間が読むものではない。

...

package com.renban.erq053.czp008;

/**...

鑑賞する »