1 通过ROWID访问表--索引
你可以采用基于ROWID的访问方式情况,提高访问表的效率, , ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系. 通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高.
2 共享SQL语句--相同的sql放入缓存
3 选择最有效率的表名顺序(只在基于规则的优化器中有效) 最右边的表作为基础表(记录最少,效率最高)
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.
例如:
表 TAB1 16,384 条记录
表 TAB2 1 条记录
选择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
4. WHERE子句中的连接顺序.
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
5 用EXPLAIN PLAN 分析SQL语句
EXPLAIN PLAN 是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句. 通过分析,我们就可以知道ORACLE是怎么样连接表,使用什么方式扫描表(索引扫描或全表扫描)以及使用到的索引名称.
6.分页sql
一般的分页sql如下所示:
sql1:select * from (select t.*,rownum rn from XXX t)where rn>0 and rn <10;
sql2:select * from (select t.*,rownum rn from XXX t where rownum <10)where rn>0;
乍看一下没什么区别,实际上区别很大...125万条数据测试,
sql1平均需要1.25秒(咋这么准呢? )
sql2平均需要... 0.07秒
原因在于,子查询中,sql2排除了10以外的所有数据
当然了,如果查询最后10条,那效率是一样的
7.多Exists,少in
Exists只检查存在性,性能比in强很多,有些朋友不会用Exists,就举个例子
例,想要得到有电话号码的人的基本信息,table2有冗余信息
select * from table1;--(id,name,age)
select * from table2;--(id,phone)
in:
select * from table1 t1 where t1.id in (select t2.id from table2 t2 where t1.id=t2.id);
Exists:
select * from table1 t1 where Exists (select 1 from table2 t2 where t1.id=t2.id);
(补充内容)用in的朋友注意了,当参数超过1000个,数据库就挂了。(oracle 10g数据库)
8.少用*
很多朋友很喜欢用*,比如:select * from XXX;
一般来说,并不需要所有的数据,只需要一些,有的仅仅需要1个2个,
拿5W的数据量,10个属性来测试:
(这里的时间指的是PL/SQL Developer显示所有数据的时间)
使用select * from XXX;平均需要20秒,
使用select column1,column2 from XXX;平均需要12秒
(我的机子不是很好。。。)
对于开发来说,这一条是个灾难,知道是一回事,做就是另一回事了
9 一些查询往往会联接十几张甚至几十张表
应用设计的时候对这样的查询要很慎重。如果表格很大,十几张表做联接,肯定不会有好的性能。如果应用是支持数据分析系统,那可能还好。如果应用是一个OLTP系统(要求很快返回结果),这样的设计失败的风险可能会很大。有时候可能需要降低数据库范式级别,多保存一些冗余数据列,以减少表格联接的数量
10 慎用distinct关键字
distinct在查询一个字段或者很少字段的情况下使用,会避免重复数据的出现,给查询带来优化效果。
但是查询字段很多的情况下使用,则会大大降低查询效率。因为当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较,过滤的过程则会毫不客气的占用系统资源,cpu时间。
11 like
去掉前置百分号。like语句会因为前置百分号而无法使用索引
12 使用存储过程
可以考虑使用存储过程封装那些复杂的SQL语句或商业逻辑,这样做有几个好处。
一是存储过程的执行计划可以被缓存在内存中较长时间,减少了重新编译的时间。
二是存储过程减少了客户端和服务器的繁复交互。
三是如果程序发布后需要做某些改变你可以直接修改存储过程而不用修改程序,避免需要重新安装部署程序。
13 复杂sql
对于非常复杂的sql(特别是有多层嵌套,带子句或相关查询的),应该先考虑是否设计不当引起的。对于一些复杂SQL可以考虑使用程序实现。
14 避免In子句
使用In 或 not In子句时,特别是当子句中有多个值时,且查询数据表数据较多时,速度会明显下降。可以采用连接查询或外连接查询来提高性能。