首页

关于Oracle数据库SQL及索引原理过程图析并结合具体示例进行简单说明帮助进行设计优化

标签:sql优化,索引设计,性能优化,oracle性能,sql原理,b-tree索引,位图索引,全表扫描,/*+index()*/     发布时间:2018-02-01   

一、前言

1.关于Oracle RDBMS执行SQL系统层面10个步骤,具体如下所示,详细见下图所示

1. User访问Oracle Server之前提交一个请求(包含了db_name、instance_name、username、password等信息),Oracle Server接收到请求并通过Password File的验证后,分配SGA内存池,启动后台进程同时创建并启动实例。@b@2. 在启动实例之后User Process与Server Process建立Connect。@b@3. 再通过Server process和Oracle Instance完成建立Sesscion。@b@4. 用户执行SQL语句,由server process接收到并直接与Oracle交互。@b@5. SQL语句通过Server Process到达Oracle Instance,再将SQL载入数据库缓冲区。@b@6. Server Process通知Oracle Database将与SQL语句相关的数据块副本加载到缓冲区中。@b@7. 在数据库缓存区执行SQL语句,并产生”脏缓冲区”。@b@8. 由CKPT检查点进程检查到”脏缓冲区”,并调用DBWn数据库写进程,但在DBWn执行之前,应该由LGWR先将数据文件的原始状态、数据库的改变等信息记录到Redo Log Files。@b@9. 将更新的内容写入到磁盘中的数据文件。@b@10. 返回结果给用户

关于Oracle数据库SQL及索引原理过程图析并结合具体示例进行简单说明帮助进行设计优化

2.SQL执行顺序

1、from子句组装来自不同数据源的数据;@b@2、where子句基于指定的条件对记录行进行筛选;@b@3、group by子句将数据划分为多个分组;@b@4、使用聚集函数进行计算;@b@5、使用having子句筛选分组;@b@6、计算所有的表达式;@b@7、select 的字段;@b@8、使用order by对结果集进行排序。
(8)SELECT  (9) DISTINCT (11) <TOP_specification> <select_list> @b@(1) FROM <left_table>  @b@(3) <join_type> JOIN <right_table> @b@(2) ON <join_condition> @b@(4) WHERE <where_condition> @b@(5) GROUP BY <group_by_list> @b@(6) WITH {CUBE | ROLLUP} @b@(7) HAVING <having_condition> @b@(10) ORDER BY <order_by_list>

3.索引优化

oracle的常见有b-tree索引(默认、CREATE INDEX语句时)、位图索引bitmap(字段枚举值)、Hash索引、函数索引(带函数操作)、分区索引、全局索引、反向索引、聚族索引、非聚族索引

1、索引应该经常建在Where子句经常用到的列上,且大表常用字段进行查询,且检索行数在总表行数的5-15%。则应该考虑。@b@2、两表连接的字段,建立索引@b@3、Order By后面常用字段,则也经过进行索引。@b@4、不应该在小表上建设索引。@b@5、where子句中有OR 操作符或单独引用Job 列(索引列的后面列) 则将不会走索引,将会进行全表扫描@b@6、LIKE '%ABC%' 索引失效, 'ABC%' 可以经过索引@b@7、Not Null/Null索引失效@b@8、索引列上不要使用函数,如SELECT column1 FROM tab1 WHERE substr(name,1,3) = 'ABC'@b@9、索引列上不能进行计算SELECT column1 FROM tab1 WHERE column1/10>10 则索引失效,改成SELECT column1 FROM tab1 WHERE column1>10*10 @b@10、索引列上不要使用NOT(!=、 <>)如:SELECT column1 FROM tab1 WHERE column1 ! = 10 改成:SELECT column1 FROM tab1 WHERE column1 > 10 OR column1 < 10 。@b@11、用UNION替换OR@b@12、用EXISTS替代IN、用NOT EXISTS替代NOT IN@b@13、复合索引,必须使用主索引列,如复合索引(deptno,job),则WHERE deptno=20 AND job=’MANAGER’ √、WHERE deptno=20 √、WHERE job=’MANAGER’ AND deptno=20 √、WHERE job=’MANAGER’ ×

4.全表扫描/*+index(a,INEX_CON_CREATE_DATE)index(b,IDX_CD_CON_ID)*/应用示例

select /*+index(a,INEX_CON_CREATE_DATE)index(b,IDX_CD_CON_ID)*/a.cname,@b@           a.ctype,@b@             a.ccode,@b@             b.data_status,@b@             count(1) dcount@b@        from cms_con_detail b@b@            left join  cms_content a on b.content_id = a.id@b@                and b.data_status='1'@b@            where  a.con_create_date > to_date('2018-01-01', 'yyyy-mm-dd')  @b@           group by a.cname,@b@                a.ctype,@b@                a.ccode,@b@                b.data_status@b@          order by a.ccode,a.cname,a.ctype  asc

二、示例分析

1.Where后面条件执行筛选顺序从右->左(下面语句第1条执行不报错,第2条会提示除数不能为零)

1.Select  'ok'  From Dual Where 1 / 0 = 1 And 1 = 2;@b@2.Select  'ok'  From Dual Where 1 = 2 And 1 / 0 = 1;

2.复合索引示例

Create Index i_deptno_job on emp(deptno,job); —>在emp表的deptno、job列建立索引。@b@select * from emp where deptno=66 and job='sals' ->走索引。@b@select * from emp where deptno=66 OR job='sals' ->将进行全表扫描。不走索引@b@select * from emp where deptno=66 ->走索引。@b@select * from emp where job='sals' ->进行全表扫描、不走索引。@b@//如果在where 子句中有OR 操作符或单独引用Job 列(索引列的后面列) 则将不会走索引,将会进行全表扫描。