数据库性能优化手法

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')
语句 2SELECT * 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'
);
语句 2SELECT 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
语句 2SELECT * 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.事务
若是要执行一系列的操做,而这些操做最终是以总体的原子操做的形式完成的话,
事务就是必须的。关于事务的理论中,银行转帐问题是最经典的例子:当把钱从一个银
行账号转移至另一个银行账号的时候,这个操做要由两个步骤来完成,首先要将资金
从一个银行账号取出,而后再将其存入另外一个银行账号。若是资金已经从一个银行账号
取出了,在将资金存入另外一个银行账号以前或者进行当中发生异常状况 ( 包括程序内部
异常、服务器当机、目标账号被冻结 ) ,若是没有事务保护就会出现源账号中的资金已
经减小了,可是目标账号中的资金并无增长的情况。
事务是关键业务系统开发中很是关键性的服务,对于关键性业务系统若是没有采用事
务,那么这个系统能够说是不可用的。
相关文章
相关标签/搜索