操作环境:AIX +11g+PLSQL
包含以下内容:
1. SQL语句执行过程
2. 优化器及执行计划
3. 合理应用Hints
4. 索引及应用实例
5. 其他优化技术及应用
1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。
2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。
3)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。
4)表达式转换, 将复杂的 SQL 表达式转换为较简单的等效连接表达式。
5)选择优化器,不同的优化器一般产生不同的“执行计划”
6)选择连接方式, ORACLE 主要有三种连接方式,对多表连接ORACLE会选择适当的连接方式。
7)选择连接顺序, 对多表连接 ORACLE 选择哪一对表先连接,选择这两表中哪张表做为基础数据表。
8)选择数据的搜索路径,根据以上条件选择合适的数据搜索路径,比如,是选用全表搜索还是利用索引或是其他的方式。
9)运行“执行计划”
我们可以通过如下语句来查询缓存中的执行计划:
SELECT t1.*,
't2-->',
t2.*
FROM v$sql_plan t1
JOIN v$sql t2
ON t1.address = t2.address
AND t1.hash_value = t2.hash_value
AND t1.child_number = t2.child_number;--缓存中的执行计划。
1)from子句组装来自不同数据源的数据;
2)where子句基于指定的条件对记录行进行筛选;
3)group by子句将数据划分为多个分组;
4)使用聚集函数进行计算;
5)使用having子句筛选分组;
6)计算所有的表达式;
7)计算select的字段;
8)使用order by对结果集进行排序。
如下图所示:
说明:
*这是一张SQL语句执行过程图
*执行计划是SQL语句执行过程中必然用到的
*执行计划是优化器(Optimizer)的产物
*两种不同的方式:CBO和RBO
查看优化器设置:
方法一:
SELECT VALUE FROM v$parameter t WHERE t.name = 'optimizer_mode';
showparameter optimizer_mode
*CBO用到了字典中的Statistics,而RBO没有
分析统计信息相关SQL:
analyze table tablename compute statistics;
analyze table tablename compute statistics for all indexes
analyze table tablename delete statistics
关于执行计划的一些知识:
可以查看参数:
show parameter STATISTICS_LEVEL
慎用hint,可能会产生严重的后果,比如append会产生锁块,导致并发资源等待等
create table t_1(owner varchar2(30),table_name varchar2(30));
create table t_2(owner varchar2(30),table_name varchar2(30));
insert into t_1 SELECT owner,table_name FROM dba_tables;
insert into t_2 SELECT owner,view_name FROM dba_views t;
create index idx_t_1 on t_1(table_name);
create index idx_t_2 on t_2(table_name);
analyze table t_1 compute statistics;
analyze table t_2 compute statistics;
SELECT *
FROM (SELECT * FROM t_1
UNION ALL
SELECT * FROM t_2) aa
WHERE aa.table_name LIKE 'Z%'; ---- Full Table Scans
SELECT /*+ index(AA.t_1 idx_t_1) index(AA.t_2 idx_t_2)*/ *
FROM (SELECT * FROM t_1
UNION ALL
SELECT * FROM t_2) AA
WHERE AA.table_name LIKE 'Z%'; ---- Index Scans
逻辑上:
Single column 单列索引
Concatenated 多列索引
Unique 唯一索引
Non-Unique 非唯一索引
Function-based函数索引
Domain 域索引
*普通索引列 a is not null 按逻辑改为a>0或a>''
*like操作改写
*能用union all绝不用union,除非要去重
例1.用合适的索引来避免不必要的全表扫
如果要在索引列查询is not null条件,建议列加上is not null约束,默认值约束,
然而确实由于某种原因索引列设计为null,还想通过is null条件走索引,该如何是好呢?请看
drop table t_tab1;
create table t_tab1 as
SELECT t.owner,
t.object_name,
t.object_type,
t.created,
t.last_ddl_time
FROM dba_objects t;
analyze table t_tab1 compute statistics;
create index idx01_t_tab1 on t_tab1(last_ddl_time);--普通索引
set autotrace trace;
SELECT * FROM t_tab1 t where t.last_ddl_time is null;
如上情况调整为复合索引
drop index idx01_t_tab1;
create index idx01_t_tab1 on t_tab1(last_ddl_time,1);--加了个常量
set autotrace trace;
SELECT * FROM t_tab1 t where t.last_ddl_time is null;
drop table t_tab1 purge;
create table t_tab1 as
SELECT t.owner,
t.object_name,
t.object_type,
t.OBJECT_ID,
t.created,
t.last_ddl_time
FROM dba_objects t;
CREATE INDEX IDX01_T_TAB1 ON T_TAB1(object_name);
analyze table t_tab1 compute statistics;
set autot trace
SELECT * FROM t_tab1 t where t.object_name like '%20121231';
改进索引,此处使用反转函数索引,此外经常用到的函数索引还有,instr(),substr()等
drop index IDX01_T_TAB1;
CREATE INDEX IDX02_T_TAB1 ON T_TAB1(reverse(object_name));
analyze table t_tab1 compute statistics;
SELECT * FROM t_tab1 t where reverse(t.object_name) like reverse('%20121231');
执行计划如下:
并行技术,并行执行目标SQL语句,这实际上是以额外的资源消耗来换取执行时间的缩短,很多情况下使用并行是针对某些SQL的唯一优化手段。
使用shell调度或其他调度工具。
SQL语句级别的并行:/*+parallel*/
/*+ parallel(table_name 4)*/
表压缩技术
compress
NOLOGGING
减少日志
Partition技术
分而治之
中间表/临时表事务分解思路
‘大事化小’
求平衡
CPU,Memory很强大,IO存在瓶颈(最普遍的情况)
使用新特性
insertall 啦 使用listagg()比wm_concat()快大概50倍、row_number()等分析函数
软硬件资源合理搭配
黔驴技穷,要求加硬件资源? Boss会对你说,找会计去吧,提前给你开工资 ……
SQL的优化的手段是五花八门、不一而足的,包括但不限于如下措施: