当然,改变语句的写法只是语句优化的一种手段之一,在这个基础上,在结合其他的优化手段(采用PLSQL块提花单个语句、采用游标、提示等)才能取得最好的优化效果。以下的替换中,大多数情况下,右边的写法会优于左边的写法,并且根据等价原理进行互换,可以在复杂语句中组合成多种写法:
SELECT B
FROM T
WHERE C = 1
OR C = 2;
=>
SELECT B
FROM T
WHERE C IN (1,2);
SELECT B
FROM T1
WHERE C IN (SELECT C FROM T2 WHERE A=’aaa’);
=>
SELECT B
FROM T1
WHERE EXISTS (SELECT 1 FROM T2 WHERE A=’aaa’ and T1.C = T2.C);
SELECT B FROM T1
WHERE B IN
(SELECT B FROM T2);
=>
SELECT DISTINCT T1.B FROM T1,
T2
WHERE T1.B=T2.B
SELECT B FROM TT1
INTERSECT
SELECT B FROM TT2;
=>
SELECT DISTINCT T1.B FROM T1,
T2
WHERE T1.B=T2.B
SELECT DISTINCT T1.B
FROM T1, T2
WHERE T2.A=’aaa’
and T1.C = T2.C;
WHERE EXISTS (SELECT 1 FROM T2 WHERE A=’aaa’ and T1.C = T2.C);
=>
SELECT B
FROM T1
WHERE EXISTS (SELECT 1 FROM T2 WHERE A=’aaa’ and T1.C = T2.C);
SELECT B
FROM T1
WHERE EXISTS (SELECT 1 FROM T2 WHERE A=’aaa’ and T1.C = T2.C);
=>
SELECT T1.B
FROM T1, T2
WHERE T2.A=’aaa’
and T1.C = T2.C;
WHERE EXISTS (SELECT 1 FROM T2 WHERE A=’aaa’ and T1.C = T2.C);
SELECT B
FROM T1
WHERE C NOT IN (SELECT C FROM T2 WHERE A=’ccc’);
=>
SELECT B
FROM T1
WHERE NOT EXISTS (SELECT 1 FROM T2 WHERE A=’ccc’ AND T1.B = T2.B);
SELECT B
FROM T1
WHERE C NOT IN (SELECT C FROM T2 WHERE A=’ccc’);
=>
SELECT B
FROM T1 Ta,
(SELECT C FROM T2 WHERE A=’ccc’) Tb
WHERE Ta.C = Tb.C(+)
AND Tb.C IS NULL;
SELECT B
FROM T1
WHERE C NOT IN (SELECT C FROM T2 WHERE A=’ccc’);
=>
SELECT /*+ HASH_AJ */B
FROM T1
WHERE C NOT IN (SELECT C FROM T2 WHERE A=’ccc’);
优化器缺省是用嵌套循环来处理anti-joins的,但是如果使用了MERGE_AJ、HASH_AJ、NL_AJ提示,NOT IN能够被转换为一个排序合并或hash anti-join。
SELECT T1.B, T2.C
FROM T1, T2
WHERE T1.A = T2.A(+);
=>
SELECT T1.B,
(SELECT T2.C FROM T2 WHERE T1.A = T2.A)
FROM T1;
当T1和T2都比较大,且T2的A上有索引时,第二个写法效率很高。当然,T2只能返回一个字段
SELECT T1.B, T2.C, T2.B
FROM T1, T2
WHERE T1.A = T2.A(+);
=>
SELECT B, to_number(substr(T2_DATA, 1 10)) T2_C, substr(T2_DATA, 11) T2_A
FROM
(
SELECT T1.B,
(SELECT NVL(to_char(T2.C, fm0000000009),rpad(‘ ’, 10))||T2.B FROM T2 WHERE T1.A = T2.A) T2_DATA
FROM T1
);
=>
CREATE OR REPLACE TYPE AS OBJECT (A T2.A%TYPE, C T2.C%TYPE);
/
SELECT B, T2_DATA.A T2_A, T2_DATA.C T2_C
FROM
(
SELECT T1.B,
(SELECT TYPE_A_C(T2.A, T2.C) FROM T2 WHERE T1.A = T2.A) T2_DATA
FROM T1
);
SELECT *
FROM T1
WHERE T1.A = (SELECT MAX(T2.A) FROM T2 WHERE T1.B=T2.B)
=>
SELECT T1.*
FROM T1, (SELECT T2.B, MAX(T2.A) T2_A FROM T2 GROUP BY B) T22
WHERE T1.B = T22.B
AND T1.A = T22.T2_A
GROUP BY在不同情况下可以用不同方式转换:
SELECT B, COUNT(B)
FROM T
GROUP BY B;
假如A的取值范围为1,2,3
=>
SELECT COUNT(DECODE(B,1,’X’,NULL)) AS “B1”,
COUNT(DECODE(B,2,’X’,NULL)) AS “B2”,
COUNT(DECODE(B,3,’X’,NULL)) AS “B3”
FROM T;
SELECT C
FROM T
GROUP BY C
HAVING MAX(B) < 3
=>
SELECT C
FROM T
WHERE B < 3
MINUS
SELECT C
FROM T
WHERE B >=3;
SELECT C
FROM T
GROUP BY C
HAVING COUNT(B) > 1;
=>
SELECT DISTINCT C
FROM T t1
WHERE ROWID > (SELECT MIN(ROWID) FROM T t2 WHERE t1.C = t2.C);
SELECT C, MAX(A)
FROM T
GROUP BY C;
=>
SELECT DISTINCT C, MAX(A) OVER (PARTITION BY C)
FROM T
SELECT C
FROM T
GROUP BY C
HAVING B < 3;
=>
SELECT C
FROM T
WHERE B < 3;
GROUP BY C;
SELECT B
FROM T1
WHERE A>1
MINUS
SELECT C
FROM T2
WHERE A>2;
=>
SELECT DISTINCT B
FROM T1
WHERE A>1
AND B NOT IN (SELECT B FROM T2 WHERE A>2);
SELECT B
FROM T
WHERE AIS NULL
OR A=2
=>
SELECT B
FROM T
WHERE A IS NULL
UNION
SELECT B
FROM T
WHERE A=2
SELECT B
FROM T1
WHERE A>1
UNION
SELECT B
FROM T2
WHERE A<3;
=>
SELECT DISTINCT B
FROM
(
SELECT B
FROM T1
WHERE A>1
UNION ALL
SELECT B
FROM T2
WHERE A<3
);
[@more@]来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9650775/viewspace-920369/ ,如需转载,请注明出处,否则将追究法律责任。