はじめに
CodeIgniter 3.06で確認しました。
CodeIgniterには、Active Record(クエリビルダ)という機能があります。
これはあらかじめ用意されているメソッドを利用することで、SQLを書かずにクエリを発行する機能です。
一番シンプルな形はこれですね。
$query = $this->db->get('mytable');
これを実行すると、mytableの全レコードを取得します。
その他
- select()
- select_max()
- from()
- join()
- where()
- like()
- group_by()
- distinct()
- order_by()
- insert()
- update()
- delete()
といった対応するSQLをイメージできるメソッドが用意されています。
そんな中
- limit()
というメソッドがあります。
limit()の構文はこうです。
limit(取得レコード数, オフセット)
21~30のレコードを取得したい場合は、
$this->db->limit(10,20);
のように書きます。
これはどのようなSQLが生成されるのでしょうか。MySQLはわかるのですが、Oracleはどうなるのでしょうか。
想定する結果を返してくれるのでしょうか。今回の調査の目的はここです。
というわけで、MySql、PostgreSql、Oracleでこのlimit()を使った場合にどのようなSQLが生成されるのかを調べてみました。
sampleテーブルから20件目から10件(21~30件目)を取得するソースです。
実際のソースはこのようになっています。
$this->db->limit(10,20);
$query = $this->db->get('sample');
return $query->result();
では、実際に発行されるSQLを確認してみます。
MySqlの場合
SELECT * FROM `sample` LIMIT 20, 10
想定どおりですね。MySQLは行数の制限がラクでよいですね。
PostgreSqlの場合
SELECT * FROM "sample" LIMIT 10 OFFSET 20
Postgresあまり使ったことなかったのですが、LIMITが用意されているのですね。
こちらも納得な感じです。
Oracleの場合
SELECT * FROM
(
SELECT
inner_query.*, rownum rnum
FROM
(SELECT * FROM "sample" ) inner_query
WHERE
rownum < 31
)
WHERE rnum >= 21
やっぱりOracleはこうなるしかないですよね。limit句がないので。
というようにoracleの場合は自動的にインラインビューとrownumを使ったSQLが組み立てられるという結果になりました。
データ量が多くなると性能的に厳しそうですが、フレームワークでこの差分を吸収してくれるのは助かりますね。