MySQLで
id:int | name:varchar | num:int |
---|
みたいなテーブルに
SELECT * FROM stock WHERE num=’1′
みたいなクエリを投げる。
厳密に言えば、numはint型で、クォーテーションでくくったものは文字列型であるから、数値=文字列の比較は常に成立しないのだけど、MySQLは気を利かせてnum=1を検索して返してくれる。
しかし、このとき、インデックスは動作しない。 型をミスってSQL文を埋め込んでいても勝手に変換して動作するくせに、インデックスが働かずボトルネックになるというアレな状態だ。
適当な感じのインデックスが張ってあるのに、EXPLAINしてやると使用キーが無かったりするのはこんな原因だったりする。
普通にSQLを自分で構築している場合には、コードを修正してクォーテーションを外せば良い。
この問題は、表題のZend Frameworkにもあって、自動エスケープモードを有効にしていると、型に関係なく勝手にクォーテーションでくくられてしまう。 ZendFrameworkのDB機能ではSELECT * FROM stock WHERE num=:numみたいなSQL文とarray(‘num’=>1)の様なパラメータを渡してやるわけだけど、自動エスケープモードで発行するとSELECT * FROM stock WHERE num=’1′になってしまうので、インデックスが働かない状態になる。
このような場合、DBインスタンスを作るときに自動エスケープを無効化して、必要なパラメータを手動でエスケープしなければならない。 また、自動エスケープ処理部分で、is_string($var)の場合だけクォーテーションをかけるようにフレームワーク側を修正する手もある(面倒な場合、DB定義をALTER TABLE stock CHANGE num num VARCHAR(11)のようにして文字列型にしてしまう手もある)
(442)