例如: 表 TAB1 16,384 条记录表 TAB2 5 条记录,选择TAB2作为基础表 (最好的方法) select count(*) from tab1,tab2 执行时间0.96秒,选择TAB2作为基础表 (不佳的方法) select count(*) from tab2,tab1 执行时间26.09秒;
如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表
例如:
EMP表描述了LOCATION表和CATEGORY表的交集
SELECT *
FROM LOCATION L,
CATEGORY C,
EMP E
WHERE E.EMP_NO BETWEEN 1000 AND 2000
AND E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
将比下列
SQL更有效率
SELECT *
FROM EMP E ,
LOCATION L ,
CATEGORY C
WHERE E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
AND E.EMP_NO BETWEEN 1000 AND 2000
2.WHERE子句中的连接顺序
SQLSERVER采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾
例如:
(低效,执行时间156.3秒)
SELECT *
FROM EMP E
WHERE SAL > 50000
AND JOB = ’MANAGER’
AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO);
(高效,执行时间10.6秒)
SELECT *
FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = ’MANAGER’;
4.减少访问数据库的次数。当执行每条
SQL语句时,
SQLSERVER在内部执行了许多工作:解析
SQL语句,估算索引的利用率,绑定变量,读数据块等等
由此可见,减少访问数据库的次数,就能实际上减少
SQLSERVER的工作量,例如:
以下有三种方法可以检索出雇员号等于0342或0291的职员
方法1 (最低效)
SELECT EMP_NAME, SALARY, GRADE
FROM EMP
WHERE EMP_NO = 342;
SELECT EMP_NAME, SALARY, GRADE
FROM EMP
WHERE EMP_NO = 291;
方法2 (次低效)
DECLARE
CURSOR C1 (E_NO NUMBER) IS
SELECT EMP_NAME,SALARY,GRADE
FROM EMP
WHERE EMP_NO = E_NO;
BEGIN
OPEN C1(342);
FETCH C1 INTO …,…,…;
…
OPEN C1(291);
FETCH C1 INTO …,…,…;
…
CLOSE C1;
END;
方法2 (高效)
SELECT A.EMP_NAME, A.SALARY, A.GRADE,
B.EMP_NAME, B.SALARY, B.GRADE
FROM EMP A, EMP B
WHERE A.EMP_NO = 342
AND B.EMP_NO = 291;
5.使用DECODE函数来减少处理时间
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表
例如:
SELECT COUNT(*), SUM(SAL)
FROM EMP
WHERE DEPT_NO = ’0020’
AND ENAME LIKE ’SMITH%’;
SELECT COUNT(*), SUM(SAL)
FROM EMP
WHERE DEPT_NO = ’0030’
AND ENAME LIKE ’SMITH%’;
你可以用DECODE函数高效地得到相同结果
SELECT COUNT(DECODE(DEPT_NO, ’0020’, ’X’, NULL)) D0020_COUNT,
COUNT(DECODE(DEPT_NO, ’0030’, ’X’, NULL)) D0030_COUNT,
SUM(DECODE(DEPT_NO, ’0020’, SAL, NULL)) D0020_SAL,
SUM(DECODE(DEPT_NO, 0030, SAL, NULL)) D0030_SAL
FROM EMP
WHERE ENAME LIKE ’SMITH%’;
例如:
低效
SELECT REGION, AVG(LOG_SIZE)
FROM LOCATION
GROUP BY REGION
HAVING REGION REGION != ’SYDNEY’
AND REGION != ’PERTH’
高效
SELECT REGION, AVG(LOG_SIZE)
FROM LOCATION
WHERE REGION REGION != ’SYDNEY’
AND REGION != ’PERTH’
GROUP BY REGION
7.减少对表的查询
在含有子查询的
SQL语句中,要特别注意减少对表的查询
例如:
低效
SELECT TAB_NAME
FROM TABLES
WHERE TAB_NAME = (SELECT TAB_NAME
FROM TAB_COLUMNS
WHERE VERSION = 604)
AND DB_VER = (SELECT DB_VER
FROM TAB_COLUMNS
WHERE VERSION = 604)
高效
SELECT TAB_NAME
FROM TABLES
WHERE (TAB_NAME, DB_VER) = (SELECT TAB_NAME, DB_VER
FROM TAB_COLUMNS
WHERE VERSION = 604)
Update多个Column例子:
低效
UPDATE EMP
SET EMP_CAT = (SELECT MAX(CATEGORY)
FROM EMP_CATEGORIES),
SAL_RANGE = (SELECT MAX(SAL_RANGE)
FROM EMP_CATEGORIES)
WHERE EMP_DEPT = 0020;
高效
UPDATE EMP
SET (EMP_CAT, SAL_RANGE) = (SELECT MAX(CATEGORY), MAX(SAL_RANGE)
FROM EMP_CATEGORIES)
WHERE EMP_DEPT = 0020;