アカウント名:
パスワード:
「ブラインド」SQLインジェクションって、区別するものなのかな?SQLインジェクションそのものだと思うんだけど。SQLインジェクションの種類わけならそれでもいいと思うんだが、何か別物のように聞こえてしまって/扱っているようで、違和感感じました。
PHPのソーシャルアプリを使っている人間に聞いたら、PDOでPlaceFolderを使ったクエリ作成(prepare使うやつ)は、使わないんだとか。PDOって処理速度が重いので、PV稼がなくてはいけないソーシャルアプリには不適切なんだとか。教科書どおりなら、SQLインジェクション防ぐのはprepare()が有効だと思うんだが・・・
さすがPHPer、期待に違わぬ残念さ。Javaで速度を稼ぐためにPreparedStatementをやめたなんて話は聞いたことがないなあ(検索条件が動的に変化するので使えなかったということはあるけど)。むしろかえってparseが必要な分遅くなるとしか思えないんだけど。実はDBMSがなんちゃってPreparedStatementしか用意されていないMySQLだったなんてオチはないよね。
prepared statement ってクエリキャッシュに載せるために使うものでコネクションプーリングとはあまり関係ないと思ってたんですがあってますかね?「毎回DB接続をオープン、クローズした時のSQL解析」を高速化するためのの物という把握でした。
DBは幾らか分かるんですが、アプリは素人なんで変なコト言ってるかもしれませんけど…。
> 違うなら生SQLの方がはやいですよね??なんで?
そもそもどうしてstatementがキャッシュされることがないなんて非現実的な仮定にこだわるんですか? 性能が重要なサーバじゃなかったの?
毎回コネクションクローズしてたらそのコストがでか過ぎて、preparedだろうとそうでなかろうと大した差がない。
そもそもプーリングがご法度って本当なの?ソース出してくれませんかね?
なら最初からPHP+MySQLの話と書けばいいのに。それに叩かれてるのはpconnectじゃなくてprepared statementの話だよね。prepared statementでなく、生文字列を組み立てて速度を稼ぐのは明らかにバッドノウハウ。他のツリーにもあるけど、PDOとMySQLの実装がバカなのが原因。
>PHPの高負荷サイトでpconnect使わないのは比較的常識の部類それは比較的常識に考えていいけど、まぁバッドノウハウの類だな。
pconnect 自体が単なる永続的接続で、にコネクションプールと呼べる物じゃ無いって事を忘れてるよ。
そういう当てこすりをしたいなら、技術論の場には出てこないほうがいいんじゃないかな。多くは技術的に正しいか正しくないかを論議しようとしてるよね。
#1926755 の論点を洗うと、1. コネクションプーリングはソーシャルアプリ界隈ではご法度2. Prepared Statementを使うとSQLのパースは遅いのではないかの二点になると思うけど、これでいい?
1に関して繋がっているのは #1926785 #1926836 #1927085 で叩きになってるようには見えないけどどうかな。#1926793 の「本当にこれ合ってるの?」に対して反論が出てきてないのが気になる。#1927085 の通りだとするとMySQL特有で、PHP+Pos
逆。prepared statementを使うとクエリキャッキュがきかないhttp://dev.mysql.com/doc/refman/5.1/ja/query-cache-how.html [mysql.com]
http://dev.mysql.com/doc/refman/5.1-olh/ja/query-cache.html [mysql.com]
注意MySQL 5.1.17 以降、項4.5.5.1. 「クエリキャッシュの動作」に説明されている条件の下で、クエリーキャッシュは準備済みステートメントに使用されます。5.1.17 より前では、クエリーキャッシュは準備済みステートメントに使用されません。
読んでみたら、もう少しバージョンによる制限がきつかったようで。http://dev.mysql.com/doc/refman/5.1-olh/ja/query-cache-operation.html [mysql.com]
MySQL 5.1.21 より前では、PREPARE および EXECUTE で実行された準備済みステートメントの場合、? パラメータマーカーを含んでいるものはキャッシュされません。
とあるので、5.1.21以降であれば普通に使えるように読めますが、いかがでしょう?
# しかし、キャッシュが使用されない場合の注意書きが多いですね…
色々コメントついてるけど論点がずれてない?別にprepared statement が重要な訳じゃないと思うけど。要はエスケープ処理を確実にする為なんだからプレースフォルダを解決する関数ひとつ作ればいいだけじゃん。1っ箇所だけならまず間違えないし、prepared statement 使ってる人なら簡単な説明で理解してくれるはずだし。
ソーシャルアプリ業界ではプーリングするのは逆にご法度
これってどんな理由でご法度にしているのでしょう。効率性の問題ではないように思えるのですが。
自己レス。元ネタはきっとこの辺ですね。Lampで作るソーシャルアプリの負荷対策~アプリとインフラの調和のテクニック~ [slideshare.net]。DB接続への待ち行列を少なくすることが重要な負荷対策であると。
接続だけして作業してないコネクションがDBの負荷に影響を与えるのだろうかと。メモリ増やしてDB側の接続上限を上げればよいだけに見えますが、少し実験してみないと分からないところで。
RDMS の機能の半分を占める (!) コネクション認証/識別を使用してない、ってことと等価ですからねえ。
論より証拠で、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)に設定を変更する必要があります。
人生の大半の問題はスルー力で解決する -- スルー力研究専門家
っていうか、これ (スコア: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をやめたなんていってるとはおもえないんですけど・・・
Re:っていうか、これ (スコア:2)
prepared statement ってクエリキャッシュに載せるために使うものでコネクションプーリングとはあまり関係ないと思ってたんですがあってますかね?
「毎回DB接続をオープン、クローズした時のSQL解析」を高速化するためのの物という把握でした。
DBは幾らか分かるんですが、アプリは素人なんで変なコト言ってるかもしれませんけど…。
Re:っていうか、これ (スコア:1)
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=5374&forum=12 [atmarkit.co.jp]
> PreparedStatementによりプリコンパイルされたSQLは
> コネクションをクローズした後もキャッシュされているのでしょうか?
コネクションクローズしたあともプリコンパイルされたSQLが保持されているということであれば納得です!
違うなら生SQLの方がはやいですよね??
Re: (スコア:0)
> 違うなら生SQLの方がはやいですよね??
なんで?
Re:っていうか、これ (スコア:1)
【プリコンパイルあり】
prepared,execute(プリコンパイルされたSQL) 2回通信または2回実行
【プリコンパイルなし】
execute(生SQL) 1回通信または1回実行
だとおもうんですが?ちがいますか?
Re: (スコア:0)
そもそもどうしてstatementがキャッシュされることがないなんて非現実的な仮定にこだわるんですか? 性能が重要なサーバじゃなかったの?
Re:っていうか、これ (スコア:1)
ぼくが書いた内容をちゃんと読んでますか?
こだわるってるんじゃなくてわからなくてずっと質問してるんですが・・・
質問してる人間に質問で返すなと・・・
PDOでコネクションクローズしたあとでもstatementがキャッシュにのっているのであればおっしゃるとおりだと思います。
ただ、コネクションクローズしたあとでもstatementのキャッシュがつかえるのかどうかそこがわからんのです。
そしてその部分はだれも教えてくれない・・・
Re: (スコア:0)
毎回コネクションクローズしてたらそのコストがでか過ぎて、
preparedだろうとそうでなかろうと大した差がない。
そもそもプーリングがご法度って本当なの?
ソース出してくれませんかね?
Re:っていうか、これ (スコア:1)
もう他の人がだしてるよ・・・
Re: (スコア:0)
Re:っていうか、これ (スコア:1)
ソーシャルアプリ界隈って言ったのが癪に障ったのかえらく叩かれてしまいました。
ソーシャルアプリに限らずPHPの高負荷サイトでpconnect使わないのは比較的常識の部類だと思ってたんですけどね(グッドノウハウなのかバッドノウハウなのかはさておいてね)。
それにしても「使う技術によってノウハウは違うよ」って言っただけのつもりだったのに何でこんなに叩かれたんだか・・・
Re: (スコア:0)
なら最初からPHP+MySQLの話と書けばいいのに。
それに叩かれてるのはpconnectじゃなくてprepared statementの話だよね。
prepared statementでなく、生文字列を組み立てて速度を稼ぐのは明らかにバッドノウハウ。
他のツリーにもあるけど、PDOとMySQLの実装がバカなのが原因。
Re: (スコア:0)
Re:っていうか、これ (スコア:2)
>PHPの高負荷サイトでpconnect使わないのは比較的常識の部類
それは比較的常識に考えていいけど、まぁバッドノウハウの類だな。
pconnect 自体が単なる永続的接続で、にコネクションプールと呼べる物じゃ無いって事を忘れてるよ。
Re: (スコア:0)
そういう当てこすりをしたいなら、技術論の場には出てこないほうがいいんじゃないかな。
多くは技術的に正しいか正しくないかを論議しようとしてるよね。
#1926755 の論点を洗うと、
1. コネクションプーリングはソーシャルアプリ界隈ではご法度
2. Prepared Statementを使うとSQLのパースは遅いのではないか
の二点になると思うけど、これでいい?
1に関して繋がっているのは #1926785 #1926836 #1927085 で叩きになってるようには見えないけどどうかな。
#1926793 の「本当にこれ合ってるの?」に対して反論が出てきてないのが気になる。
#1927085 の通りだとするとMySQL特有で、PHP+Pos
Re:っていうか、これ (スコア:1)
http://srad.jp/security/comments.pl?sid=527293&cid=1926729 [srad.jp]
で、私の意見は「使う技術によってノウハウは違うよね?」「詳細聞かずに残念いっちゃだめだよ」の2点ですよ?
他の発言に関しては質問してる内容を質問でかえされたから私はこう思ってるんだけど違うのかな?って考えをいっただけで議論するつもりはないですよ・・・
そんな議論ができるほど立派なエンジニアではないですから・・・
> 叩きが入っているようには見えないんだがどう?
その後馬鹿馬鹿言われてたので、たたかれたと表現しましたけどね・・・馬鹿とかいわれなければたたかれたとは言いませんよ。それとも馬鹿と相手に対して言い放つのは議論であって叩いてないということでしょうか?
Re:っていうか、これ (スコア:1)
逆。prepared statementを使うとクエリキャッキュがきかない
http://dev.mysql.com/doc/refman/5.1/ja/query-cache-how.html [mysql.com]
Re:っていうか、これ (スコア:2)
http://dev.mysql.com/doc/refman/5.1-olh/ja/query-cache.html [mysql.com]
Re:っていうか、これ (スコア:2)
読んでみたら、もう少しバージョンによる制限がきつかったようで。
http://dev.mysql.com/doc/refman/5.1-olh/ja/query-cache-operation.html [mysql.com]
とあるので、5.1.21以降であれば普通に使えるように読めますが、いかがでしょう?
# しかし、キャッシュが使用されない場合の注意書きが多いですね…
Re: (スコア:0)
Re:っていうか、これ (スコア:2)
色々コメントついてるけど論点がずれてない?
別にprepared statement が重要な訳じゃないと思うけど。
要はエスケープ処理を確実にする為なんだからプレースフォルダを解決する関数ひとつ作ればいいだけじゃん。
1っ箇所だけならまず間違えないし、prepared statement 使ってる人なら簡単な説明で理解してくれるはずだし。
Re: (スコア:0)
これってどんな理由でご法度にしているのでしょう。
効率性の問題ではないように思えるのですが。
Re: (スコア:0)
自己レス。
元ネタはきっとこの辺ですね。
Lampで作るソーシャルアプリの負荷対策~アプリとインフラの調和のテクニック~ [slideshare.net]。
DB接続への待ち行列を少なくすることが重要な負荷対策であると。
接続だけして作業してないコネクションがDBの負荷に影響を与えるのだろうかと。
メモリ増やしてDB側の接続上限を上げればよいだけに見えますが、少し実験してみないと分からないところで。
Re: (スコア:0)
RDMS の機能の半分を占める (!) コネクション認証/識別を使用してない、ってことと等価ですからねえ。
計測してみたよ (スコア: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アプリケーションでコネクションプーリングしたくなるのも納得です。
あくまで私の知識の範囲内ですが…… (スコア:0)
プリペアードクエリ:クライアント側で利用選択する機能。
実行計画を事前に作成し、実際にいれる値だけを変えて連続実行
→ どちらかというと実行計画の使いまわしより
プレースホルダによる自動エスケープの恩恵が大きい。
ステートメントキャッシュ:サーバ側自動機能。
プリペアードクエリの実行計画をキャッシュ。
→ あまり意味がないとのことでサーバ側で無効にされている
クエリキャッシュ:サーバ側自動機能。意外とパフォーマンスに影響
問い合わせで同じデータを返すものをキャッシュ。
→ パラメータ付きのプリペアード