MS Accessの最適化のナゾ
以前、ちょっと遅くて困っていたSQLがありました。
元はこれ。
-- Ver. 1 select id, max(time) from ( select id, time, (select count(*) from log where id = t1.id and time < t1.time) as count, (select count(*) from log where id = t1.id group by id) as total from log t1) where count < total * 0.9 group by id;
会社の人に聞いてまわって、教えてもらったのがこれ。
totalを求める副問合せを外に出して、結合しています。
-- Ver. 2 select t1.id, max(t1.time) from ( select id, time, (select count(*) from log where id = t2.id and time < t2.time) as count from log t2) t1 inner join (select id, count(*) as total from log group by id) t3 on t1.id = t3.id where t1.count < t3.total * 0.9 group by t1.id;
最近「副問合せ要らないんじゃない?」と言われて、もう一度見直したのがこれ。
確かにjoinで書けますね。
-- Ver. 3 select t3.id, max(t3.time) from ( select t1.id, t1.time, count(*) as count from log t1 left join log t2 on t1.id = t2.id and t1.time > t2.time group by t1.id, t1.time) t3 inner join (select id, count(*) as total from log group by id) t4 on t3.id = t4.id where t3.count < t4.total * 0.9 group by t3.id;
で、こいつらの性能を測定してみたところ、Accessの場合とOracleの場合とで、だいぶ振る舞いが違いました。
Access | Oracle | |
1 | △ | △ |
2 | ○ | △ |
3 | △ | ○ |
どういう最適化をしているのか。謎です。