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に比べたら大したこと無いので
既存コードを直すほどの話じゃないが、これからやるところはキャストにしよう。
この記事も直しておきました。