简单整理oracle日常应用笔记。
1、采用excel表格中的数据直接粘贴数据库记录中,默认会在后面加一个空格“”,操作完成后一定要记得对空格匹配然后修改一下。
2、查询数据库里的所有表结构,
采用select * from dba_tables(sys登录);
查看某个用户所拥有的表:select * from all_tables WHERE owner='SCOTT' ;
或者 SELECT * FROM DBA_TABLES WHERE OWNER='SCOTT';
3、上午在PL/SQL dev中建表时提示ORA-00907: 缺失右括号,检查sql脚本发现
eu_bctype INT(50)
Oracle中int为定长的类型,不能再规定其长度,需要改成number;
4、intersect运算
返回查询结果中相同的部分既他们的交集
1
2
3
|
select
*
from
abc
intersect
select
*
from
abc2 ;
|
5、minus运算
返回在第一个查询结果中与第二个查询结果不相同的那部分行记录,
即两个结果的差集
1
2
3
|
select
*
from
abc2
minus
select
*
from
abc ;
|
6、TO_CHAR格式化小数点输出
1
|
select
To_char(
sum
(score),9999999.99)
from
score;
|
7、有很多种方法可以用来找出哪些SQL语句需要优化,但是很久以来,最简单的方法都是分析保存在VSQL视图中的缓存的SQL信息。通过VSQL视图,可以确定具有高消耗时间、CUP和IO读取的SQL语句
查看总消耗时间最多的前10条SQL语句
1
2
3
4
5
6
7
8
9
10
|
select
*
from
(
select
v.sql_id,
v.child_number,
v.sql_text,
v.elapsed_time,
v.cpu_time,
v.disk_reads,
rank() over(
order
by
v.elapsed_time
desc
) elapsed_rank
from
v$sql v) a
where
elapsed_rank <= 10;
|
查看CPU消耗时间最多的前10条SQL语句
1
2
3
4
5
6
7
8
9
10
|
select
*
from
(
select
v.sql_id,
v.child_number,
v.sql_text,
v.elapsed_time,
v.cpu_time,
v.disk_reads,
rank() over(
order
by
v.cpu_time
desc
) elapsed_rank
from
v$sql v) a
where
elapsed_rank <= 10;
|
查看消耗磁盘读取最多的前10条SQL语句
1
2
3
4
5
6
7
8
9
10
|
select
*
from
(
select
v.sql_id,
v.child_number,
v.sql_text,
v.elapsed_time,
v.cpu_time,
v.disk_reads,
rank() over(
order
by
v.disk_reads
desc
) elapsed_rank
from
v$sql v) a
where
elapsed_rank <= 10;
|
8、oracle优化操作
(1)不用“<>”或者“!=”操作符。对不等于操作符的处理会造成全表扫描,可以用“<” or “>”代替
不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。
推荐方案:用其它相同功能的操作运算代替,
如:
1
2
|
a<>0 改为 a>0
or
a<0
a<>’’ 改为 a>’’
|
(2)选择最有效率的表名顺序(只在基于规则的优化器中有效):
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须
选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.
(3)WHERE子句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
(4)SELECT子句中避免使用 ‘ * ‘
ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间
(5)减少访问数据库的次数:
ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等;
(6)在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200
(7)使用DECODE函数来减少处理时间:
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.DECODE(input_value,value,result[,value,result…][,default_result]);
(8)删除重复记录:
最高效的删除重复记录方法 ( 因为使用了ROWID)例子:
1
2
|
DELETE
FROM
EMP E
WHERE
E.ROWID > (
SELECT
MIN
(X.ROWID)
FROM
EMP X
WHERE
X.EMP_NO = E.EMP_NO);
|
(9)用TRUNCATE替代DELETE:
当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是
恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者
按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)
(10)用Where子句替换HAVING子句:
避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的
开销. (非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可
以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就
剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having
就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而
having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一
个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后
再决定放在那里。
(11)使用表的别名(Alias):
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
(12)用EXISTS替代IN、用NOT EXISTS替代NOT IN:
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中,NOT IN子句将执
行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer
Joins)或NOT EXISTS.
例子:
(高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(13)sql语句用大写的;因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行
(14)避免在索引列上使用NOT
我们要避免在索引列上使用NOT, NOT会产生和在索引列上使用函数相同的影响. 当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描.
(15)避免在索引列上使用计算.
WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.
举例:
低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(16)用>=替代>
1
2
3
4
|
高效:
SELECT
*
FROM
EMP
WHERE
DEPTNO >=4
低效:
SELECT
*
FROM
EMP
WHERE
DEPTNO >3
|
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.
(17)避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.
低效: (索引失效)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
高效: (索引有效)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
(18)索引的弊端
a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高.
b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!
(19)可能引起全表扫描的操作
在索引列上使用NOT或者“<>”
对索引列使用函数或者计算
NOT IN操作
通配符位于查询字符串的第一个字符
IS NULL或者IS NOT NULL
多列索引,但它的第一个列并没有被Where子句引用
9、oracle SQL分页查询处理
分页取11到20的记录,两种查询方法,如下,
第一种的速度会比较快点,因为在tab1这层先过滤掉了一部分数据,第二种方法到最外层再进行处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
--分页查询1
SELECT
TAB2.*
FROM
(
SELECT
tab1.*, ROWNUM row_num
FROM
(
--把需要分页的sql直接放进来就行了
SELECT
t.*
FROM
T_T_DEPT t
) TAB1
WHERE
ROWNUM<21
) TAB2
WHERE
TAB2.row_num >10
--分页查询2
SELECT
TAB2.*
FROM
(
SELECT
tab1.*, ROWNUM row_num
FROM
(
--把需要分页的sql直接放进来就行了
SELECT
t.*
FROM
T_T_DEPT t
) TAB1
) TAB2
WHERE
TAB2.row_num
BETWEEN
11
AND
20
|