今天優(yōu)化了一個sql語句,感覺速度好像是快了點,自己想想覺得也是,下面給出類似的例子,工作中的表就不拿來舉例了。實際我們平常都在憑著自己的感覺在寫SQL,其實跳出那個圈子你會發(fā)現(xiàn)能寫出更好的。
一、先給出我的表和數(shù)據(jù),這里數(shù)據(jù)量少,可能不明顯,只是表明一下這個意思!
create table EMP ( EMPNO NUMBER(4) not null, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7,2), DEPTNO NUMBER(2) ); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7369, 'SMITH', 'CLERK', 7902, to_date('17-12-1980', 'dd-mm-yyyy'), 800, 20); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7499, 'ALLEN', 'SALESMAN', 7698, to_date('20-02-1981', 'dd-mm-yyyy'), 1600, 30); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7521, 'WARD', 'SALESMAN', 7698, to_date('22-02-1981', 'dd-mm-yyyy'), 1250, 30); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7566, 'JONES', 'MANAGER', 7839, to_date('02-04-1981', 'dd-mm-yyyy'), 2975, 20); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7654, 'MARTIN', 'SALESMAN', 7698, to_date('28-09-1981', 'dd-mm-yyyy'), 1250, 30); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7698, 'BLAKE', 'MANAGER', 7839, to_date('01-05-1981', 'dd-mm-yyyy'), 2850, 30); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7782, 'CLARK', 'MANAGER', 7839, to_date('09-06-1981', 'dd-mm-yyyy'), 2450, 10); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7788, 'SCOTT', 'ANALYST', 7566, to_date('19-04-1987', 'dd-mm-yyyy'), 3000, 20); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7844, 'TURNER', 'SALESMAN', 7698, to_date('08-09-1981', 'dd-mm-yyyy'), 1500, 30); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7876, 'ADAMS', 'CLERK', 7788, to_date('23-05-1987', 'dd-mm-yyyy'), 1100, 20); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7900, 'JAMES', 'CLERK', 7698, to_date('03-12-1981', 'dd-mm-yyyy'), 950, 30); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7902, 'FORD', 'ANALYST', 7566, to_date('03-12-1981', 'dd-mm-yyyy'), 3000, 20); insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO) values (7934, 'MILLER', 'CLERK', 7782, to_date('23-01-1982', 'dd-mm-yyyy'), 1300, 10); commit;
二、假設(shè)有這樣一個需求,我要得到這個表中所有低于所在部門平均工資的員工的基本信息。很自然的 我們會寫出這樣的SQL:
這種寫法是很通常的寫法,也很好理解,從字面上看都知道是什么意思!但是在一個很大的表中這樣來統(tǒng)計是很慢很慢的,對于每一條記錄都要嵌套的查詢一個子查詢,這樣對性能影響是很大的。
三、為什么不跳出這個思維的定式,換一種方法來統(tǒng)計呢,我給出下面的方法:
SELECT A.* FROM emp A, (SELECT deptno, AVG(sal) sal FROM emp GROUP BY deptno) B WHERE A.deptno = B.deptno AND A.sal < B.sal;這里沒有使用嵌套子查詢,而是使用了關(guān)聯(lián)子查詢 ,這樣實際上也是很好理解的,但是往往我們很少這樣寫。
四、總的來說我還是很喜歡下面的寫法,在數(shù)據(jù)量很大的情況下,對性能的提高真的不少,但是在數(shù)據(jù)量小的情況下似乎看不出什么效果。實際上也是,如果 數(shù)據(jù)量小,根本不會涉及到優(yōu)化,我在這里說也沒什么用。如果覺得自己的子查詢有問題,看看能不能把嵌套子查詢轉(zhuǎn)化為關(guān)聯(lián)子查詢,效果還是挺明顯的。