1.建立必要的索引 (在常常检索的字段进行建立索引,好比以图书名称来进行检索,就须要在这个图书名称的字段建立索引)
2.使用预编译查询(
程序中一般是根据用户的输入来动态执行
SQL
语句,这时应该尽可能使用参数化
SQL
,这样不只能够避免
SQL
注入漏洞攻击,最重要数据库会对这些参数化
SQL
执行
预编译,这样第一次执行的时候
DBMS
会为这个
SQL
语句进行查询优化而且执行预编
译,这样之后再执行这个
SQL
的时候就直接使用预编译的结果,这样能够大大提升执
行的速度。)
3.调整 WHERE 子句中的链接顺序
DBMS
通常采用自下而上的顺序解析
WHERE
子句,根据这个原理
,
表链接最好写
在其余
WHERE
条件以前,那些能够过滤掉最大数量记录。
好比下面的
SQL
语句性能较差:
SELECT *
FROM T_Person
WHERE FSalary > 50000
AND FPosition= ‘MANAGER’
AND 25 < (SELECT COUNT(*) FROM T_Manager
WHERE FManagerId=2);
咱们将子查询的条件放到最前面,下面的
SQL
语句性能比较好:
SELECT *
FROM T_Person
WHERE
25 < (SELECT COUNT(*) FROM T_Manager
WHERE FManagerId=2)
AND FSalary > 50000
AND FPosition= ‘MANAGER’ ;
4.SELECT语句中避免使用'*'
5.尽可能将多条 SQL语句压缩到一句SQL中
6.用Where子句替换 HAVING
子句(
避免使用
HAVING
子句,由于
HAVING
只会在检索出全部记录以后才对结果集
进行过滤。若是能经过
WHERE
子句限制记录的数目,那就能减小这方面的开销。
HAVING
中的条件通常用于聚合函数的过滤,除此而外,应该将条件写在
WHERE
子
句中
)
7. 使用表的别名
当在
SQL
语句中链接多个表时,请使用表的别名并把别名前缀于每一个列名上。这
样就能够减小解析的时间并减小那些由列名歧义引发的语法错误。
8.用EXISTS替代 IN
在查询中,为了知足一个条件,每每须要对另外一个表进行联接,在这种状况下,使
用
EXISTS
而不是
IN
一般将提升查询的效率,由于
IN
子句将执行一个子查询内部的排
序和合并。下面的语句
2
就比语句
1
效率更加高。
语句
1
:
SELECT * FROM T_Employee
WHERE FNumber> 0
AND FDEPTNO IN (SELECT FNumber
FROM T_Department
WHERE FMangerName = 'Tome')
语句 2:
SELECT * FROM T_Employee
WHERE FNumber > 0
AND EXISTS (SELECT 1
FROM T_Department
WHERE T_Department. FDEPTNO = EMP.FNumber
AND FMangerName = ‘MELB’ )
9.用表链接替换 EXISTS
一般来讲,表链接的方式比
EXISTS
更有效率,所以若是可能的话尽可能使用表连
接替换
EXISTS
。下面的语句
2
就比语句
1
效率更加高。
语句
1
:
SELECT FName FROM T_Employee
WHERE EXISTS
(
SELECT 1 FROM T_Department
WHERE T_Employee.FDepartNo= FNumber
AND FKind='A'
);
语句 2:
SELECT FName FROM T_Department, T_Employee
WHERE T_Employee. FDepartNo = T_Departmen. FNumber
AND FKind = ‘A ’ ;
10.避免在索引列上使用计算
在
WHERE
子句中,若是索引列是计算或者函数的一部分,
DBMS
的优化器将不
会使用索引而使用全表扫描。
例以下面的
SQL
语句用于检索月薪的
12
倍大于两万五千元的员工:
SELECT *FROM T_Employee
WHERE FSalary * 12 >25000;
因为在大于号左边的是
FSalary
与
12
的成绩表达式,这样
DBMS
的优化器将不会
使用字段
FSalary
的索引,由于
DBMS
必须对
T_Employee
表进行全表扫描,从而计算
FSalary * 12
的值,而后与
25000
进行比较。将上面的
SQL
语句修改成下面的等价写法
后
DBMS
将会使用索引查找,从而大大提升了效率:
SELECT *FROM T_Employee
WHERE FSalary >25000/12;
一样的,不能在索引列上使用函数,由于函数也是一种计算,会形成全表扫描。下
面的语句
2
就比语句
1
效率更加高。
语句
1
:
SELECT * FROM T_Example
WHERE ABS(FAmount)=300
语句 2:
SELECT * FROM T_Example
WHERE FAmount=300 OR FAmount=-300
11.用UNION ALL 替换 UNION
当
SQL
语句须要
UNION
两个查询结果集合时,即便检索结果中不会有重复的记
录,若是使用
UNION
这两个结果集一样会尝试进行合并,而后在输出最终结果前进行
排序。
所以,若是检索结果中不会有重复的记录的话,应该用
UNION ALL
替代
UNION
,这
样效率就会所以获得提升。下面的语句
2
就比语句
1
效率更加高。
语句
1
:
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS1
WHERE TRAN_DATE = '20010101'
UNION
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS2
WHERE TRAN_DATE ='20010102'
语句
2
:
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS1
WHERE TRAN_DATE ='20010101'
UNION ALL
SELECTACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS2
WHERE TRAN_DATE = '20010102'
12.避免隐式类型转换形成的全表扫描
T_Person
表的字符串类型字段
FLevel
为人员的级别,在
FAge
字段上建有索引。
咱们执行下面的
SQL
语句用于检索全部级别等于
10
的员工:
SELECT FId,FAge,FName
FROM T_Person
WHERE FAge=10
在这个
SQL
语句中,将字符串类型字段
FLevel
与数值
10
进行比较,因为在大部
分数据库中隐式转换类型中数值类型的优先级高于字符串类型,所以
DBMS
会对
FAge
字段进行隐式类型转换,至关于执行了下面的
SQL
语句:
SELECT FId,FAge,FName
FROM T_Person
WHERE TO_INT(FAge)=10
因为在索引字段上进行了计算,因此形成了索引失效而使用全表扫描。所以应将
SQL
语句作以下修改:
SELECT FId,FAge,FName
FROM T_Person
WHERE FAge='10'
13.防止检索范围过宽
若是
DBMS
优化器认为检索范围过宽,那么它将放弃索引查找而使用全表扫描。
下面是几种可能形成检索范围过宽的状况:
使用
IS NOT NULL
或者不等于判断,可能形成优化器假设匹配的记录数太多。
使用
LIKE
运算符的时候,
"a%"
将会使用索引,而
"a%c"
和
"%c"
则会使用全表扫描,因
此
"a%c"
和
"%c"
不能被有效的评估匹配的数量。
14.事务
若是要执行一系列的操做,而这些操做最终是以总体的原子操做的形式完成的话,
事务就是必须的。关于事务的理论中,银行转帐问题是最经典的例子:当把钱从一个银
行账号转移至另一个银行账号的时候,这个操做要由两个步骤来完成,首先要将资金
从一个银行账号取出,而后再将其存入另外一个银行账号。若是资金已经从一个银行账号
取出了,在将资金存入另外一个银行账号以前或者进行当中发生异常状况
(
包括程序内部
异常、服务器当机、目标账号被冻结
)
,若是没有事务保护就会出现源账号中的资金已
经减小了,可是目标账号中的资金并无增长的情况。
事务是关键业务系统开发中很是关键性的服务,对于关键性业务系统若是没有采用事
务,那么这个系统能够说是不可用的。