Oracle数据库SQL基础用法与优化总结
前言................................................................................................................................. 2
基础用法.......................................................................................................................... 2
一、 SELECT语句 ....................................................................................... 2 二、
三、
四、
五、
六、
七、
八、
九、
十、 多表关联.............................................................................................. 2 子查询 ................................................................................................. 3 级联查询(Hierachical Querys) ................................................................ 5 INSERT语句........................................................................................ 6 UPDATE语句 ...................................................................................... 7 DELETE语句....................................................................................... 7 集合操作符 .......................................................................................... 8 DISTINCT............................................................................................ 8 聚集查询的用法 ..................................................... 错误!未定义书签。
十一、 ROLLUP 、CUBE、Grouping SETS用法.............................................. 9
十二、 Flashback闪回技术............................................................................... 9
十三、 伪列(Pseudocolumns)...................................................................... 10
十四、 MERGE ............................................................................................. 10
SQL语句调优 ................................................................................................................ 12
一、
二、
三、
四、
五、
六、
七、
八、
九、 避免使用’*’ ................................................................................... 12 删除重复记录..................................................................................... 12 计算记录条数..................................................................................... 12 减少对表的查询 ................................................................................. 12 EXISTS 与IN使用 ............................................................................ 13 使用索引............................................................................................ 13 使用where代替having语句 ............................................................... 15 使用表的别名..................................................................................... 15 表记录删除 ........................................................................................ 16
十、 Decode函数使用 ................................................................................ 16
十一、 尽量少用子查询 ................................................................................. 17
十二、 尽量少用视图(View) ...................................................................... 17
十三、 减少不必要的排序.............................................................................. 17
十四、 调优方法( Explain Plan) ...................................................................... 17
PL/SQL的使用............................................................................................................... 18
一、
二、 简介................................................................................................... 18 PL/SQL特点 ...................................................................................... 19
前言
本文档分为三部分,第一部分为SQL语句的一些基础用法,第二部分为SQL语句的调优,第三部分简要介绍一下PL/SQL
第一部分,SQL语句的基础用法部分主要是针对常用的SQL语句语法进行整理,包括一些常用语法以及一些实用的SQL技术,可为开发人员充实SQL基础知识
第二部分,SQL语句调优,对于系统数据库调优包括硬件调优、操作系统调优、数据库配置调优、数据建模调优以及SQL语句调优,在这里主要是针对与开发有关的SQL语句调优进行一下整理与总结,希望能对开发人员写出高效SQL语句或对SQL进行调优有所帮助。
第三部分,简要介绍一下PL/SQL,并列举一些PL/SQL的特点 因本人能力有限,在整理文档过程中难免有错误或疏漏,还请大家批评指正。 基础用法
一、 SELECT语句
1、 语法
Select 列表
From 表名
Where 条件
Group by 列表
Order by 列表
对于Select语句后可跟For update
二、 多表关联
在多表关联查询时,使用表关联关系进行数据查询,其结果按关联方式不同而有差异,下面就对各种关联方式进行说明
1、 Cross-Join
SELECT * FROM division, managerof;
结果:两表的笛卡尔乘积
2、 Join (Inner join) 内连接
SELECT * FROM division a
JOIN managerof on b on a.id = b.id ;
结果:两表中满足关联条件的行被取出
Join USING(字段) 用法
SELECT gl.generalledger_id, coa.coa#, t.text AS type,
st.text AS subtype, coa.text as coa, gl.dr, gl.cr, gl.dte
FROM type t JOIN coa USING(type)
JOIN subtype st USING(subtype)
JOIN generalledger gl ON(gl.coa# = coa.coa#);
若两表中的关联字段相同,可使用Using 用法
3、 Natural Join 自然连接
自然连接是在两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回所有符合条件按的结果
SELECT * FROM division NATURAL JOIN managerof;
结果:就是按两个表中所有类型与列名相同的字段进行关联,满足条件的记录返回 Natural 关键字也适用于外连接
4、 Left join (Left Outer Join ) 左外连接
Select * from a
Left join b on a.id = b.id
结果:a 表中数据全部返回,b表中满足关联条件的数据关联返回
5、 Right join (Right Outer Join) 右外连接
Select * from a
Right join b on a.id = b.id
结果:b 表中数据全部返回,a表中满足关联条件的数据关联返回
6、 Full Outer Join全外连接
Select * from a
Full Outer join b on a.id = b.id
结果:a、b满足关联条件的记录关联在一起返回,a、b两表中不满足关联关系的记录也返回,对应的关联表字段为空
7、 多表、复杂关联
一个关联语句有多个表、多种关联关系
Select * from a
Inner join b on a.id = b.id
Left join c on b.name = c.name 注:关键字Natural也可用在外关联上
三、 子查询
子查询也是SQL语句中常用的技术方法,通常有如下几种分类
1、 单行子查询
返回一行的子查询
2、 多行子查询
返回多行的子查询
3、 多列子查询
返回多列的子查询
4、 规则子查询
子查询与外层语句无关
SELECT * FROM department WHERE division_id IN (SELECT division_id FROM division);
5、 关联子查询
子查询与外层语句有关联
SELECT * FROM division WHERE EXISTS
(SELECT division_id FROM department
WHERE division_id = division.division_id);
子查询用途
1、 在SELECT语句中
SELECT p.project_id,
(SELECT projecttype_id FROM projecttype
WHERE projecttype_id = p.projecttype_id)
FROM project p;
2、 在WHERE语句中
SELECT project_id FROM project
WHERE projecttype_id IN
(SELECT projecttype_id FROM projecttype);
SELECT division_id FROM division
WHERE division_id IN
(SELECT division_id FROM department
WHERE department_id IN
(SELECT department_id FROM department));
3、 在Order by 语句中
SELECT name FROM projecttype
ORDER BY (SELECT ‘name’ FROM DUAL);
4、 在Having 语句中
SELECT name, COUNT(name) FROM projecttype GROUP BY name
HAVING name = ANY (SELECT name FROM projecttype);
5、 在From 语句中
SELECT COUNT(*) FROM (
SELECT di.name, de.name, pr.name
FROM division di
JOIN department de ON (di.division_id = de.division_id)
JOIN project pr ON (de.department_id = pr.department_id));
6、 在INSERT语句
INSERT INTO projecttype(projecttype_id, name)
VALUES((SELECT MAX(projecttype_id)+1 FROM projecttype)
,’A new project type’);
7、 在UPDATE语句
UPDATE department SET name = (SELECT name FROM division
WHERE division_id = department.division_id);
8、 在CASE语句
9、 作为函数参数
SELECT LPAD(‘xxx’,10,(SELECT * FROM DUAL)) FROM DUAL;
四、 级联查询(Hierachical Querys)
所谓级联查询,就是在同一个表内记录有层次的数据(层次为树形关系),记录的方式是通过两个字段进行关联,使用级联查询可取出满足需求的分层次数据
语法如下:
SELECT语句 [[START WITH condition1] CONNECT BY condition2]
解释:
START WITH condition1
指定级联数据的根记录(一条或多条),所有满足条件1的记录都将被当成是根纪录,假如我们不给定START WITH子句,所有的纪录都会被当成是根纪录,通常这不是我们想要的结果。condition1可以是一个子查询。
CONNECT BY condition2
指定级联数据中父纪录和子纪录之间的关系,这里的关系被表示成一个表达式,当前纪录的字段会和对应的父纪录的某个字段进行比较。condition2必须跟着一个PRIOR操作符,该操作符用于标明父纪录的字段。condtion2不能包含子查询
PRIOR是Oracle的一个内建操作符,仅用于级联查询。当我们在级联查询的CONNEC
T BY条件中使用了PRIOR操作符时,位于其后的表达式被当成是当前纪录的父纪录进行比较。
示例:
select * from employee start with id = 2 connect by prior id = manager_id order by id; connect by prior id = manager_id
意思是从当前根记录开始,查找所有符合条件的记录:他们的manager_id必须等于当前记录的id。也就是说查找所有manager_id=2的记录及其子记录
select * from employee start with id = 2 connect by id = prior manager_id order by id; connect by id = prior manager_id
意思是从当前根记录开始,查找所有符合条件的记录:他们的id必须等于当前记录的manager_id。也就是说查找所以id=1的记录
这种语法适合于不明确数据层次关系的情况下使用,如果层数明确,并且在表中记录有层级,则可使用表自连接的关联方式实现多级数据查询
五、 INSERT语句
1、 标准语法
INSERT INTO [schema.]table [ ( column [, column …] ) ]
VALUES ( { expression | DEFAULT | (subquery) }
[, { expression | DEFAULT | (subquery) } ... ] )
[ RETURNING expression [, expression ] INTO variable [,
variable ] ];
示例
INSERT INTO projecttype
VALUES (projecttype_seq.NEXTVAL, ‘A new project type’);
2、 多表插入
INSERT { FIRST | ALL }
[ WHEN condition THEN ] INTO table [ VALUES (…) ]
[ WHEN condition THEN ] INTO table [ VALUES (…) ]
ELSE INTO table [ VALUES (…) ]
subquery; ALL 只要满足WHEN 条件的就执行 FIRST 执行第一个满足WHEN条件的 ELSE 如果所有条件都不满足,则执行ELSE中内容
示例1:
insert FIRST
when 1=2 then into ta
when 2=2 then into tb
when 3=3 then into tc
else
into ttest
select * from ttest ;
结果是将ttest表中的数据插入到tb表中,第2个条件与第3个条件均满足,但FIST关键词决定执行第2个插入操作
示例1:
insert ALL
when 1=2 then into ta
when 2=2 then into tb
when 3=3 then into tc
else
into ttest
select * from ttest ;
结果是将ttest表中的数据插入到tb、tc表中,第2个条件与第3个条件均满足,ALL关键词决定执行第2个与第3个插入操作
六、 UPDATE语句
UPDATE [schema.]table
SET column = expression | (subquery) | DEFAULT
| ( column [, column … ] ) = (subquery)
[ WHERE ... ]
[ RETURNING expression [, expression ] INTO variable [,
variable ] ) ];
示例1:
DEFAULT 按列的默认值给列赋值
RETURNING 按更新的行返回一个表达式的值给变量,此用法可适用于insert、update、delete
多列的更新,通常是按每列分别赋值,但也可使用子查询同时给多个列赋值 Update 表名1
Set (column1,column2,column3) = (select value1,value2,value3 from 表名2 where 条件 ) Where 条件
七、 DELETE语句
语法:
DELETE [ FROM ] [schema.]table
[ WHERE ... ]
[ RETURNING expression [, expression ] INTO variable [,
variable ] ) ];
示例:
DELETE from department where id = 8879 returning dname into :name;
八、 集合操作符
对于集合操作符有UNION ALL、UNION、INTERSECT、MINUS
1. UNION ALL
返回两个结果集的全部记录,也包括重复的记录
例如A结果集有100条,B结果集有100条,不管是否有重复的,最后结果是返回200条
2. UNION
返回两个结果集的全部有区别的记录,对于两个结果集中重复的会进行合并后返回,
例如A结果集有100条记录,B结果集有100条记录,其中B结果集中有20条与A结果集中有重复,则返回的结果集为180条(将B中重复的20条去掉了)
因此UNION会比UNION ALL增加大量的计算,所以不是必要的情况下一定不要使用UNION,而使用UNION ALL
3. INTERSECT
返回两个结果集中重复的行,类似于一个内连接,例如A结果集有100条,B结果集有100条,其中重复的为20条,则使用INTERSECT返回的结果集为20条
4. MINUS
返回一个结果集减去另一个结果集后剩下的数据,所谓减就是将重复的部分减去 例如,A结果集有100条,B结果集有100条,其中重复的为20条,则
A
MINUS
B
的结果为80条(A中的)
九、 DISTINCT
DISTINCT是将结果集中的重复值去掉,即在所获取的结果集中,若有重复的记录则只返回一条,所谓重复的记录即每个字段均相同
Select distinct column …… from ……
如果不是必须使用则尽量少使用
十、 ROLLUP 、CUBE、Grouping SETS用法
ROLLUP、CUBE与Grouping SETS是用在分组查询中,通常用在数据仓库的计算上,但对于我们的业务系统中某些统计报表也是很有效的,下面就简要介绍一下这两个用法 ROLLUP 是按汇总列进行上卷
语法示例:
Select A,B,C,sum(D)
From 表
group by Rollup (A,B,C) \\A,B,C为分组列,D为汇总列
如果不加Rollup关键字,其结果是按A,B,C三列计算出D的汇总,加了Rollup之后,得出结果是先按(A,B,C)分组计算出汇总,再按(A,B)计算出汇总,再按(A)计算出汇总,最后计算出全部记录的汇总,并按层次关系进行排序,适用于逐级展开汇总查询
CUBE 是按组合进行汇总计算
语法示例:
Select A,B,C,sum(D)
From 表
group by Cube(A,B,C)
其结果是按如下组合形成汇总结果 (A,B,C)(A,B)(A,C)(A)(B,C)(B)(C)再加上全部记录的汇总
Grouping Sets 按指定组合进行汇总
语法示例:
Select A,B,C,sum(D)
From 表
group by Grouping sets((A,B,C) ,(A,B),(C))
其结果是按(A,B,C) ,(A,B),(C)三种分组形成汇总结果
类似于多个汇总结果集UNION ALL
十一、 Flashback闪回技术
Oracle 的闪回技术可以解决短时间内被误删除数据的问题,可恢复的时间根据数据库的参数设置有关
语法:SELECT … AS OF { SCN | TIMESTAMP } expression
可以有两种方式取回历史数据,一种是通过SCN,一种是使用TIMESTAMP,使用SCN方式比较复杂,通常我们使用TIMESTAMP方式即可
示例:如果不小心删除了表salb25中的数据,则可通过如下语句取回
select * from salb25 as of timestamp to_timestamp(‘2011-05-22 15:00:00’,’yyyy-mm-dd hh24:mi:ss’ ;
to_timestamp函数是指明取哪个时间点的数据
十二、 伪列(Pseudocolumns)
伪列是Oracle数据库提供的查询结果附带的信息,是虚列
1、 CURRVAL、NEXTVAL
序列中的伪列
Sequence.CURRVAL
Sequence.NEXTVAL
2、 ROWID
ROWID提供一种快速访问数据的方法,是直接对应的一条记录的物理地址,在取出表中的一条记录后,在结果集中会存在ROWID这个伪列,使用这个值可最快速的访问表中记录,每条记录有一个ROWID
3、 ROWNUM
ROWNUM是一个查询语句返回记录的顺序号,此顺序号是在Where语句生效后产生的,如果Where后面还有Order by排序语句,则原顺序不变
4、 LEVEL
LEVEL是级联查询中会产生的伪列,表示每条记录的层次 (从1开始) 十三、 MERGE
MERGE是被用在两个表间插入新行并更新存在的行
语法:
MERGE into 表1
USING 表2 on (两表关联条件 )
WHEN MATCHED THEN UPDATE语句
WHEN NOT MATCHED THEN INSERT语句
示例:
MERGE INTO bonuses D
USING (SELECT employee_id, salary, department_id FROM employees WHERE department_id = 80) S
ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01 WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus)
VALUES (S.employee_id, S.salary*0.1);
十四、 CASE用法
CASE可以作为一个表达式来使用,也可作为PL/SQL程序控制结构来使用
1、表达式
作为表达式来使用有如下两种用法
语法1:
Case
When 表达式1 then 结果1
When 表达式2 then 结果2
……
Else 结果n
End
返回第一个表达式为 true后面对应的结果,若没有表达式为true,则返回else 后面结果
示例:
语法2:
Case 表达式
When 值1 Then 结果1
When 值2 Then 结果2
……
Else 结果n
End
返回第一个与表达式相等的值后面的结果,若没有相等则返回else 后的结果 此表达式可以在SQL语句中来使用
2、PL/SQL程序结构
作为控制结构来使用有如下两种用法
语法1:
Case
When 表达式1 then
语句块1;
When 表达式2 then
语句块2;
……
Else
语句块n;
End Case;
执行第一个表达式为true的后面的语句块,若没有则执行else 后面的语句块 示例:
语法2:
Case 表达式
When 值1 Then
语句块1
When 值2 Then
语句块2
……
Else
语句块n
End Case;
计算出表达式的值,按第一个匹配上的值执行后面的语句块,若没有相等则执行 else 后的语句块
SQL语句调优
一、 避免使用’*’
当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.
二、 删除重复记录
最高效的删除重复记录方法 ( 因为使用了ROWID)
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO)
Oracle的ORWID用来唯一标识表中的一条记录,是这条数据在数据库中存放的物理地址
三、 计算记录条数
计算记录数一般count(*),count(1),count(索引列)三种写法,这三种方法实际的效率差不多
四、 减少对表的查询
在写SQL语句时要减少对表的查询,即能通过对表一次查询取得结果就不要查两次。 例1:
Select * from clmb01c
Where cjxsdm = (select max(cjxsdm) from clmb10)
And csqdh = (select min(csqdh) from clmb10)
Where id = 833997
可改成
Select * from clmb01c
Where (cjxsdm, csqdh)= (select max(cjxsdm),min(csqdh) from clmb10) where id = 833997;
更新也一样
Update clmb01c set (cjxsdm,csqdh) = (select max(cjxsdm),min(csqdh) from clmb10)
Where id = 833997;
当然此例还有其它写法,在此拿出只是说明观点
例2:
Update clmb01c set cdjzt = ‘1’ where id = 833997;
Select nhjje into n_hjje from clmb01c where id = 833997;
以上两语句可合成一个
Update clmb01c set cdjzt = ‘1’ where id = 833997 returning nhjje into n_hjje;
五、 EXISTS 与IN使用
对于这两个操作符,通常认为EXISTS会比IN效率高,特别是EXISTS的子查询语句可用到索引时会比IN效率高
Oracle在处理这两个操作时处理如下:
IN:Oracle将IN后面的子查询语句调入到内存,然后排序,如果记录多会非常占用系统资源
EXISTS:在每次查询时调用一次子查询语句,所以就要保证子查询语句能使用索引,否则就会全表扫描,如果记录数很多那是很可怕的事情,会产生迪卡尔乘积
结论:IN更适用于少量的值,而Exists更适用于关联子查询,对于记录大时一定要使用EXISTS,并保存子查询使用索引
对于NOT EXISTS和NOT IN一定要选用NOT EXISTS,还可使用(外连接+判断为空)
六、 使用索引
对于数据量大的表一定要建立适当的索引,正确的使用索引可以级大的提高数据检索效率,在写SQL语句时要考虑表索引的使用,但索引的缺点一是增加物理空间的占用,二是对表的增、删、改会增加一次索引的增、删、改操作,所以对于大表要建立并使用索引,但不能过多
使用索引要注意以下几点:
1. 要按索引列构造SQL语句的where条件才能使用到索引
2. 使用不等于操作符则不能使用索引
例:select col1,col2 from table1 where col1 <> ‘AA’
如果列col1是索引则此写法不能使用索引,同样还有not in (‘AA’)
那出现这种问题如何解决呢?
那就要改变这种写法,比如判断的条件值有’AA’,’BB’,’CC’
则条件改写成col1 = ‘BB’ or col1 = ‘CC’
3. 使用is NULL 则不能使用索引
如上例:where col1 is NULL 不会使用索引
对于索引列要避免出现NULL值
4. LIKE操作符的使用
对于LIKE使用时后面的条件前面不能有通配符,否则不能使用索引
select col1,col2 from table1 where col1 like ‘AA%’
col1是字符型索引列,上面的语句会用到索引,但下面的语句不会用到索引 select col1,col2 from table1 where col1 like ‘%AA%’
所以在使用时要注意
5. 不能对索引列合并计算使用
例:
SELECT NVL(SUM(NVL(NYFPSL, 0)), 0) FROM SALR02 WHERE CNF || CYF = ‘200608’
因为SALR02表的索引是CNF,CYF,所以CNF || CYF会造成全表扫描
应写成
SELECT NVL(SUM(NVL(NYFPSL, 0)), 0) FROM SALR02 WHERE CNF = ‘2006’ and CYF = ‘08’
如果是年份和月份是一个变量则写成
SELECT NVL(SUM(NVL(NYFPSL, 0)), 0) FROM SALR02 WHERE CNF = substrb(c_jhny,1,4) and CYF = substrb(c_jhny,5,2)
6. 对索引列使用函数也会造成系统不能使用索引
例:select col1,col2 from table1 where substrb(col1,1,2) = ‘AA’
索引列是col1,这种写法也是不能使用索引的
需要改成where col1 like ‘AA%’
其它情况就要按具体函数具体分析
7. 比较不匹配的数据类型时也会影响索引的使用
例:select col1,col2 from table1 where col1 = 88383
Col1是索引列,类型是varchar2(10),此种情况oracle是允许的,只是oracle在处理时会自动在列col1上加个函数使条件变成where to_number(col1) = 88383 这样就不能使用索引了
8. 避免使用OR条件
在SQL语句条件如果对于索引列使用OR条件则系统不会使用索引
例:select cjxsdm from clmb01c where cjxsdm = ‘01-01F’ or csqdh = ‘200601010003’ 不管怎么建索引你都用不上了,如果表记录多那你就想别的办法吧
9. 可以强制使用索引
例:select /*+INDEX(table1 IK_col1)*/ col1,col2 from tabl1 ;
Table1是表名,IK_col1是索引名
强制使用并不表示最优,根据具体情况定
10. 使用函数索引,对于某些日期型字段常用字符型日期作为条件查询,这种情况
可建立函数索引
如表table1中字段dczrq是日期型date,建立函数索引IK_dczrq
Create index IK_dczrq on table1(to_char(dczrq,’yyyymmdd’))
对于函数索引在使用时,要与定义时函数的格式相同
11. 对于小表(数据量小)就不要建索引了
对于小表,因为在使用时通常用不到索引,所以索引不起作用
12. 对于数据量比较大并且频繁使用的表的索引需要定期进行重建rebuiled
索引重建的标准,通常索引中的冗余记录占总索引记录的15%以上时,要进行索引重建
索引分析:
analyze index 索引名 validate structure
按分析结果决定是否重建
select a.name,case when a.lf_rows = 0 then 0 else round(a.del_lf_rows/a.lf_rows,2) * 100 end ind_used,a.del_lf_rows,a.lf_rows
from index_stats
如果ind_used >=15 则需要进行索引重建
重建索引有两个语句 rebuild 和rebuild online
Alter index 索引名 rebuild;
Alter index 索引名 rebuild online;
两者区别,如果是使用rebuild 在重建索引时会锁表的DML语句,而使用rebuild online 在重建索引时是不影响表的DML语句,但效率低(执行时间比大约4:3) 建议使用rebuild online方式
七、 使用where代替having语句
对于有些SQL语句中having条件如果可以改成where 里去写,则要放到where里去写,因为使用having是在检索出所有结果集之后才对数据进行过滤,如果将条件放到where里就会返回少的结果集,那多好!
例:select cjxsdm,count(njsje) from clmb20
Group by cjxsdm
Having cjxsdm = ‘09-23F’
此种语句一定要避免,要改成如下写法
select cjxsdm,count(njsje) from clmb20
where cjxsdm = ‘09-23F’
Group by cjxsdm
八、 使用表的别名
在写SQL语句时最好使用表的别名,特别是多表联接时,因为表的别名会减少oracle对SQL语句的解析时间
例:select cjxsdm,csqdh,cgzdm from clmb01c,clmb01d where clmb01c.id = clmb01d.id 前两个字段是clmb01c表的,后面的字段是clmb01d表的,oracle要从数据字典里去判断哪个字段是哪个表,如果改成如下写法则会省了这一步
select a.cjxsdm,a.csqdh,b.cgzdm from clmb01c a,clmb01d b where a.id = b.id
九、 表记录删除
如果删除表中记录使用delete语句,但要删除表中全部记录还可使用truncate语句,truncate语句会比delete语句效率高,并且删除的更干净,但truncate语句一定要慎用,因为他是DDL语句,执行完truncate之后会自动提交事务,所以一定要小心噢
十、 Decode函数使用
合理使用Decode函数会减少对表的检索
例:select count(*) from clmb01c where cjxsdm = ‘01-01F’ and cshbs = ‘0’;
Select count(*) from clmb01c where cjxsdm = ‘01-01F’ and cshbs = ‘1’;
此两个语句会对表clmb01c执行两次表的扫描,使用decode函数可改成一次表扫描 Select count(decode(cshbs,’0’,1,null)) count0,count(decode(cshbs,’1’,1,null)) count1
From clmb01c where cjxsdm = ‘01-01F’ and cshbs in (‘0’,’1’)
Decode函数通常还可替代UNION
示例:
SELECT stock_id||’ Out of Stock’ FROM stock WHERE qtyonhand <=0
UNION
SELECT stock_id||’ Under Stocked’ FROM stock
WHERE qtyonhand BETWEEN 1 AND min-1
UNION
SELECT stock_id||’ Stocked’ FROM stock
WHERE qtyonhand BETWEEN min AND max
UNION
SELECT stock_id||’ Over Stocked’ FROM stock
WHERE qtyonhand > max;
可以改写成
SELECT stock_id||’ ‘||
DECODE(SIGN(qtyonhand)
,-1,’Out of Stock’,0,’Out of Stock’
,1,DECODE(SIGN(qtyonhand-min)
,-1,’Under Stocked’,0,’Stocked’
,1,DECODE(sign(qtyonhand-max)
,-1,’Stocked’,0,’Stocked’,1,’Over Stocked’
))) FROM stock;
效率会得到很大提高
十一、 尽量少用子查询
特别是相关子查询。因为这样会导致效率下降。
一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行 例:
Select a.njsje,(select b.nfpsl from mdac22 b where b.cjxsdm = a.cjxsdm ) nfpsl from clmb01c a
这样写法当然是不好啦,可改成关联,怎么写自己看吧
十二、 尽量少用视图(View)
在我们的业务系统中,有很多视图在使用,因为视图将一个SQL语句封装成一个对象,使用时可象使用表那样非常方便,对于Oracle视图是不存数据的。
1、 对于单表视图,视图与表的执行效率是一样的
2、 对于多表关联形成的视图,通常会消耗较多的系统资源
要适当使用视图
十三、 减少不必要的排序
对结果集排序会对系统产生较大的开销,所以在使用Order by 语句时要考虑是否是必要的,如果不是必要的就一定不要加
在子查询中通常不要加Order by 语句(除对排序有特殊需求)
在程序过程中(如存储过程)的结果集,通常不要加Order by 语句
尽量少用Distinct,因为Distinct总会产生排序
十四、 调优方法( Explain Plan)
在满足业务需求的基础上减少系统执行SQL语句的工作,就是减少系统资源消耗,执行SQL语句通常使用硬盘读、使用内存、使用CPU计算,调优就是将系统执行SQL语句所使用的资源最小,这样效率就会最高。
减少大表的全表扫描,减少排序,比较见效的
对于SQL语句调优可以采用一些有效的优化手段,最重要的是要能自己进行分析,比较有效的分析工具是Oracle提供的解释计划 Explain Plan
1、 一种方式是可以在PLSQL DEVELOPER中使用
这种方式非常简单易行,在PLSQL中输入要分析的SQL语句,然后执行F5,即进入Explain Plan窗口,显示此语句的执行计划,并对此执行计划进行分析
2、 另一种方式是使用命令
示例:
EXPLAIN PLAN SET statement_id= ‘计划标识’
FOR
SELECT语句;
到表plan_table 中查结果,此种方式通常是在命令行方式下使用,看着不是很方便 COL Cost FORMAT 9990;
COL Rows FORMAT 999990;
COL Bytes FORMAT 99999990;
COL Query FORMAT a40;
SELECT operation||’ ‘||options||’ on ‘||object_name "Query"
,cost "Cost"
,cardinality "Rows"
,bytes "Bytes"
FROM plan_table ORDER BY id;
3、 列说明
Cost :这是综合成本,是按CPU、内存以及硬盘读写等综合计算出来的一个值
Cardinality:是估算影响的行数
Bytes:是估算影响的字节数,是按行数*本行各列所占字节数
对分析语句来说 ,通常Cost是重点,是调优的指标
在对SQL语句进行解释计划分析时,重点是要减少开销(Cost),通过调整SQL语句的实现方式,来对语句进行优化
对于解释计划中数据访问及处理方式,可参见一些相关文档,在此不尽述
PL/SQL的使用
一、 简介
PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)。PL/SQL是Oracle数据库对SQL语句的扩展。在普通SQL语句的使用上增加了编程语言的特点,所以PL/SQL就是把数据操作和查询语句组织在PL/SQL代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能或者计算的程序语言
我们常用的PL/SQL开发工具是PLSQL Developer 、Toad等 PL/SQL块由四个基本部分组成:声明、执行体开始、异常处理、执行体结束。 下面是四个部分的基本结构:
DECLARE—可选部分
变量、常量、游标、用户定义异常的声明
……
BEGIN—必要部分
SQL语句和PL/SQL语句构成的执行程序
……
EXCEPTION—可选部分
程序出现异常时,捕捉异常并处理异常
……
END;—必须部分
二、 PL/SQL特点
1、 PL/SQL不一定提供很好的性能,但可以降低SQL编码的复杂,使SQL过程可更
好的控制,也可更好的使用游标
2、 PL/SQL明显的好处是可以创建存储过程与触发器,显而易见,存储过程的好处是
集中控制并提升性能,存储过程代码在数据库服务器上执行,降低了网络传输,结果是提高了性能
3、 有些情况是不能使用一个独立的SQL语句完成需求,就需要使用PL/SQL
4、 将非常复杂的SQL脚本改到PL/SQL实现,变成一些简单的SQL语句,可以更方
便的对SQL语句进行调优
5、 较大的IF语句应该改成CASE语句,通常情况下CASE语句比IF语句更快
接确保Oracle数据库sql语句高效执行的优化总结一2410053和10046事件24110053事件我们在查看一条SQL的执行…
Oracle数据库SQL基础用法与优化总结前言2基础用法2一SELECT语句2二三四五六七八九十多表关联2子查询3级联查询Hier…
Oracle数据库中SQL语句优化研究中国电信股份有限公司石嘴山分公司任凤摘要简要介绍数据库中SQL语句优化技术并结合具体的事例探…
oraclesql语句优化1选择最有效率的表名顺序只在基于规则的优化器中有效ORACLE的解析器按照从右到左的顺序处理FROM子句…
操作符优化IN操作符用IN写出来的SQL的优点是比较容易写及清晰易懂这比较适合现代软件开发的风格但是用IN的SQL性能总是比较低的…
接确保Oracle数据库sql语句高效执行的优化总结一2410053和10046事件24110053事件我们在查看一条SQL的执行…
Oracle数据库中SQL语句优化研究中国电信股份有限公司石嘴山分公司任凤摘要简要介绍数据库中SQL语句优化技术并结合具体的事例探…
oraclesql语句优化1选择最有效率的表名顺序只在基于规则的优化器中有效ORACLE的解析器按照从右到左的顺序处理FROM子句…
操作符优化IN操作符用IN写出来的SQL的优点是比较容易写及清晰易懂这比较适合现代软件开发的风格但是用IN的SQL性能总是比较低的…
1基本的Sql编写注意事项尽量少用IN操作符基本上所有的IN操作符都可以用EXISTS代替不用NOTIN操作符可以用NOTEXIS…
单机数据库学习总结一、Linux安装1、设置光盘启动,启动Linux的安装系统,根据提示一步步安装,创建分区时选择ext3和swa…