在SQL语句中用了OR之后, 其实很不容易控制, 第一次是想让一个带两个OR的用UNION去执行, 结果用了USE_CONCAT后变成了4个UNION了, 居然没有办法让他按我想象的第一个OR进行UNION. 第二次是在索引上, OR条件导致了不能在索引上进行条件过滤. 现在遇到了第三次, 是同事发现的, 怕自已记不住, 就没有征得他的同意, 在这儿共享出来了.
有下面两个表, TYPE_ID列上值的重复性很高.
CREATE TABLE T_SMALL (TYPE_ID, ID, ...);
CREATE TABLE T_MIDDLE (TYPE_ID, ID1, ID2, ...);
运行下面的SQL时, 总是很慢, 我们已经指定用HASH JOIN, 并也指定了T_SMALL是驱动表, 百思不得其解.
SELECT .....
FROM T_SMALL S, T_MIDDLE M
WHERE S.TYPE_ID = M.TYPE_ID
AND (S.ID = M.ID1 OR S.ID = M.ID2)
第一百零一思时, 发现了原因所在, 因为OR的问题, Oracle在做HASH JOIN时只依据了TYPE_ID这个效率不高的列, 这时的PLAN中肯定出现了FILTER这样的步骤. 后来将这个语句手工改成UNION方式, 就从2个小时变成了15分钟.
SELECT .....
FROM T_SMALL S, T_MIDDLE M
WHERE S.TYPE_ID = M.TYPE_ID
AND S.ID = M.ID1
UNION ALL
SELECT .....
FROM T_SMALL S, T_MIDDLE M
WHERE S.TYPE_ID = M.TYPE_ID
AND S.ID = M.ID2 AND M.ID1 <> M.ID2
SQL语句的调优, 其实很需要功夫, 也是一门很深的学问, 如此简单的SQL, 也有很深刻的知识.