zendFrameworkでSQLが数値型がバインドで文字列で絶望したIndexが効かずに話
まずタイトルのおかしさから「落ち着け」感が現れてるわけですが。
まぁわかるひとはもうこれ以上記事を読むまでもない話ですよ。
大した件数にもなってないDBが、どうも重い。
おおかたクソクエリがあるんだろうと思ったら、3秒を超えているものがある。
パッと見は問題無いのだが、explainするとtypeがALLになってる。
Indexが効いてないんじゃそりゃ重いですね。
なぜそうなったのか。ZendでSELECTするときのソースを振り返ってみよう。
まずシンプルに。selectするときこういうことするじゃないですか。
// このクラスはextends Zend_Db_Table_Abstractとかをしてる function selectById($id) { $select = $this->select(); $select->where('id = ?', $id); $row = $this->fetchRow($select); }
そしたらこういうSQL出して欲しいじゃないですか。
SELECT * FROM `table_name` WHERE (id = 1)
懸命な読者ならお気づきだろう。引数次第ではこうなる。
SELECT * FROM `table_name` WHERE (id = '1')
そりゃ数値型の所に文字列で検索したらIndex効かないよね。
というかこれ、検索自体は成功すんのね。いっそ失敗して欲しいんですけど。
さて、既にこのシステムはたくさんのソースがあって、
いまさらこんなものを一つ一つ(int)するわけにはいかないから、
どこかの共通処理で直したい。
幸い全てのテーブルアクセス用クラスのスーパークラスがあるから…
とはいっても、「本当に文字列で正解かもしれない」ものを
十把一絡げに数値にしてしまうわけにもいかない。
じゃけん一つ一つ(int)しましょうね〜…。
マジか…今更か…。
前任者出てこい。うちの掃除と洗濯頼む。
あと俺が寝れないから代わりに寝といて。
2015/05/30 01:55追記
intval()より(int)のほうが2倍早いらしい。
PHP側のコストなんてDBに比べたら大したこと無いので
既存コードを直すほどの話じゃないが、これからやるところはキャストにしよう。
この記事も直しておきました。