アカウント名:
パスワード:
「ブラインド」SQLインジェクションって、区別するものなのかな?SQLインジェクションそのものだと思うんだけど。SQLインジェクションの種類わけならそれでもいいと思うんだが、何か別物のように聞こえてしまって/扱っているようで、違和感感じました。
PHPのソーシャルアプリを使っている人間に聞いたら、PDOでPlaceFolderを使ったクエリ作成(prepare使うやつ)は、使わないんだとか。PDOって処理速度が重いので、PV稼がなくてはいけないソーシャルアプリには不適切なんだとか。教科書どおりなら、SQLインジェクション防ぐのはprepare()が有効だと思うんだが・・・
さすがPHPer、期待に違わぬ残念さ。Javaで速度を稼ぐためにPreparedStatementをやめたなんて話は聞いたことがないなあ(検索条件が動的に変化するので使えなかったということはあるけど)。むしろかえってparseが必要な分遅くなるとしか思えないんだけど。実はDBMSがなんちゃってPreparedStatementしか用意されていないMySQLだったなんてオチはないよね。
論より証拠で、JavaでPreparedStatementを使う場合と、そうでない場合を比較してみました。単純なSELECT文で、以下の条件で10000回ループさせました。
1. PreparedStatementをループの外で生成して使い回し2. 1回ごとにPreparedStatementを生成3. 1回ごとにSQLを生成して、executeQueryで生のSQLを実行
1.が速いのは当然として、2と3のどちらが速いかが問題だと思いますが、結果としては平均で、1. 403ms2. 7124ms3. 7523ms
となりました。つまり、PreparedStatementを使わない理由はないということです。Java+Oracleでのテストなので、PHP+MySQLがヘボイ実装という可能性はありますが:P
比較するならば Java+MySQL で同じテストをしてみましょう。
DBMSの物とバージョン、使ったライブラリを明示するべきかと
ちょっと気になったので、PHP上でDBおよび接続手段を変えて測ってみました。FreeBSD 7.2-RELEASE/amd64上で、PHP 5.3.6、MySQL 5.1.33、PostgreSQL 8.4.6 を使ってます。
integer な主キーに対するSELECTを1万回実行した時の、1回あたりの処理時間(マイクロ秒)(接続は、単なるDBへの接続と切断を1万回実行)
prepare 生SQL 接続 1回だけ 毎回 生成MySQLmysql 161 44mysqli 180 48 134 48PDO 151 47 51 50MDB2 921 609 996 124PostgreSQLpg 8260 122 245 159PDO 7861 91 366 407MDB2 13045 535 1210 406
PostgreSQL はprepareしておいた方が速いですが、MySQL は毎回生SQL文を生成してもほとんど同じ。MySQL PDO だけは、毎回prepareしても似たような数値なので、内部で自前でSQL文を組み立ててるんだと思います。まあ、エスケープ処理のアルゴリズムさえ間違えてなければ、その方が速いし悪いことじゃないとは思いますが…釈然としない…
あと、こうしてみると PostgreSQLは接続にかかる時間が桁違いですね。これだと、Webアプリケーションでコネクションプーリングしたくなるのも納得です。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
「科学者は100%安全だと保証できないものは動かしてはならない」、科学者「えっ」、プログラマ「えっ」
っていうか、これ (スコア:4, 興味深い)
「ブラインド」SQLインジェクションって、区別するものなのかな?SQLインジェクションそのものだと思うんだけど。SQLインジェクションの種類わけならそれでもいいと思うんだが、何か別物のように聞こえてしまって/扱っているようで、違和感感じました。
PHPのソーシャルアプリを使っている人間に聞いたら、PDOでPlaceFolderを使ったクエリ作成(prepare使うやつ)は、使わないんだとか。PDOって処理速度が重いので、PV稼がなくてはいけないソーシャルアプリには不適切なんだとか。教科書どおりなら、SQLインジェクション防ぐのはprepare()が有効だと思うんだが・・・
-- gonta --
"May Macintosh be with you"
Re: (スコア:0)
さすがPHPer、期待に違わぬ残念さ。
Javaで速度を稼ぐためにPreparedStatementをやめたなんて話は聞いたことがないなあ(検索条件が動的に変化するので使えなかったということはあるけど)。むしろかえってparseが必要な分遅くなるとしか思えないんだけど。
実はDBMSがなんちゃってPreparedStatementしか用意されていないMySQLだったなんてオチはないよね。
Re: (スコア:1)
たとえばJAVA屋さんだとDBコネクションをプーリングするのが常識みたいになってますけど、
ソーシャルアプリ業界ではプーリングするのは逆にご法度みたいな部分があったり
ジャンルによってノウハウって違いますからね。
DBあんまり詳しくないんでまちがってたらすいませんけど、毎回DB接続をオープン、クローズしてたらprepared statementでのSQL解析をするぶん速度は落ちるのではないでしょうか?
そういう意味ではPrepare statementやめて生SQL生成してそれ投げるというのはわかる気はしますね。
月間一億PV程度のしょぼいサイト(秒間最大200PVくらい)までしか扱ったことない私はprepare statement使っても問題ないとは思いますが、ソーシャルアプリとか秒間数千から数万のクエリさばく世界ですからね。
中途半端な知識の人間が根拠なしにPreparedStatementをやめたなんていってるとはおもえないんですけど・・・
計測してみたよ (スコア:0)
論より証拠で、JavaでPreparedStatementを使う場合と、そうでない場合を比較してみました。
単純なSELECT文で、以下の条件で10000回ループさせました。
1. PreparedStatementをループの外で生成して使い回し
2. 1回ごとにPreparedStatementを生成
3. 1回ごとにSQLを生成して、executeQueryで生のSQLを実行
1.が速いのは当然として、2と3のどちらが速いかが問題だと思いますが、結果としては平均で、
1. 403ms
2. 7124ms
3. 7523ms
となりました。つまり、PreparedStatementを使わない理由はないということです。
Java+Oracleでのテストなので、PHP+MySQLがヘボイ実装という可能性はありますが:P
Re:計測してみたよ (スコア:1)
比較するならば Java+MySQL で同じテストをしてみましょう。
Re: (スコア:0)
さらに、PHP(ウェブ)の場合リクエストごとに接続するのがスタンダードだから、毎回Prepare作成しないといけない。
一度Prepareしたものを同スクリプト内で再利用する機会はほとんどない。
ローカルアプリのように起動したら終了するまで接続を維持するようなものならいいですけど、ウェブのようなものには向いてないような気もする。
ただの勉強不足ですけど。
Re:計測してみたよ (スコア:2)
DBMSの物とバージョン、使ったライブラリを明示するべきかと
Re:計測してみたよ (スコア:1)
ちょっと気になったので、PHP上でDBおよび接続手段を変えて測ってみました。
FreeBSD 7.2-RELEASE/amd64上で、PHP 5.3.6、MySQL 5.1.33、PostgreSQL 8.4.6 を使ってます。
integer な主キーに対するSELECTを1万回実行した時の、1回あたりの処理時間(マイクロ秒)
(接続は、単なるDBへの接続と切断を1万回実行)
PostgreSQL はprepareしておいた方が速いですが、MySQL は毎回生SQL文を生成してもほとんど同じ。
MySQL PDO だけは、毎回prepareしても似たような数値なので、内部で自前でSQL文を組み立ててるんだと思います。
まあ、エスケープ処理のアルゴリズムさえ間違えてなければ、その方が速いし悪いことじゃないとは思いますが…釈然としない…
あと、こうしてみると PostgreSQLは接続にかかる時間が桁違いですね。
これだと、Webアプリケーションでコネクションプーリングしたくなるのも納得です。