数据库原理理解

oracle 体系结构

共享池是oracle缓存程序数据的地方

库高速缓存:执行过的每一句SQL语句,都存有解析后的内容

解析包括语句的语法,检验提及的对象,以及确认对象的用户权限。

数据字典高速缓存区:oracle使用的系统参数

使用最近最少使用算法(Least Recently Used, LRU),用来管理共享池中的对象。

写SQL语句时,一定要考虑如果高效的使用共享池。

共享池

SQL> select sql_text,sql_id,child_number,hash_value,executions from v$sql where upper(sql_text) like '%EMPLOYEES%';

SQL_TEXT SQL_ID CHILD_NUMBER HASH_VALUE EXECUTIONS

-------------------------------------------------------------------------------- ------------- ------------ ---------- ----------

select * from employees where department_id=60 3advtjun8csb4 0 2827379044 3

select /* a comment */ * from employees where department_id=60 fs9k1uvtkk817 0 4079558695 1

SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID=60 86sbrvcmd3mv5 0 651284325 1

三条语句,返回相同的结果,但oracle认为他们是不同的,因为oracle首先将字符串转换为散列值。这个散列值就是放在库高速缓存中的关键字。

在解析中绑定变量

SQL> variable v_dept number

SQL> exec :v_dept := 10

SQL> select * from employees where department_id = :v_dept;

SQL> exec :v_dept := 60

SQL> select * from employees where department_id = :v_dept;

锁存器是oracle为了读取存放在库高速缓存或者其它内存结构中的信息时必须获得的一种锁。锁存器可以保护库高速速缓存或其它内存结构中的信息被两个同时进行的会话修改,或一个会话正要读取的信息被另一个会话修改而导致的损坏。

互拆锁:是一个序列化组件,用来阻止多个线程同时访问一个共享结构。优点是占用内存少,可以快速获取或释放。

语法解析仍然要使用锁存器。

oracle获取锁存器的频率越多,越可能触发争夺。越需要等待较长的时间。因此正确编写代码,较少使用锁存器,也就是硬解析,是非常重要的。

Paste_Image.png

测试物理读和逻辑读

E:\plustrce.sql

set echo on

drop role plustrace;

create role plustrace;

grant select on v_$sesstat to plustrace;

grant select on v_$statname to plustrace;

grant select on v_$mystat to plustrace;

grant plustrace to dba with admin option;

set echo off

SQL> conn sys/0524 as sysdba;

SQL> @'E:\plustrce.sql'

SQL>grant plustrace to scott;

SQL> grant all on employees to scott;

SQL> conn scott/scott

SQL> alter system flush buffer_cache;

SQL> alter system flush shared_pool;

SQL> set autotrace traceonly statistics;

SQL> select * from employees where department_id=60;

SQL> set autotrace off;

SQL> alter system flush buffer_cache;

SQL> alter system flush shared_pool;

SQL> set autotrace traceonly statistics;

SQL> select * from employees where department_id=60;

SQL> set autotrace off;

应开发出更多重用共享池和缓冲区缓存中信息的代码。

查询转换

发生在查询执行完语法和权限检查之后,优化器为了决定最终的执行计划而为不同的计划计算成本预估之前。转换和优化是两个不同的任务。

视图合并

--对于大多数select-project-join(SPJ)类型查询会自动应用简单视图合并

select *

from orders o, (select sales_rep_id from orders) o_view

where o.sales_rep_id = o_view.sales_rep_id(+)

and o.order_total > 10000;

--不使用提示

select *

from orders o, (select /*+ NO_MERGE */ sales_rep_id from orders) o_view

where o.sales_rep_id = o_view.sales_rep_id(+)

and o.order_total > 10000;

--不使用提示

--当查询包含聚合计算如group by, distinct或外关联时,就会使用复杂的视图合并,从而消除包含聚合计算的视图,使用更少的资源生成结果集。

select e1.last_name,e1.salary,v.avg_salary

from employees e1,

(select department_id,avg(salary) avg_salary from employees e2 group by department_id) v

where e1.department_id=v.department_id and e1.salary>v.avg_salary;

--使用merge提示

select /*+ MERGE(v) */ e1.last_name,e1.salary,v.avg_salary

from employees e1,

(select department_id,avg(salary) avg_salary from employees e2 group by department_id) v

where e1.department_id=v.department_id and e1.salary>v.avg_salary;

--关闭_complex_view_merging

alter session set "_complex_view_merging"=FALSE;

explain plan for

select /*+ MERGE(v) */ e1.last_name,e1.salary,v.avg_salary

from employees e1,

(select department_id,avg(salary) avg_salary from employees e2 group by department_id) v

where e1.department_id=v.department_id and e1.salary>v.avg_salary;

select * from table(dbms_xplan.display);

--如果_complex_view_merging=False,即使用了MERGE,也不会进行视图合并

子查询解嵌套

--不相关子查询的解嵌套转换

select *

from employees

where employee_id in (select manager_id from departments);

explain plan for

select *

from employees

where employee_id in (select manager_id from departments);

select * from table(dbms_xplan.display);

--使用NO_UNNEST提示

--不进行查询转换将会选用filter运算而不是nested loops连接 filter效率更低

select *

from employees

where employee_id in (select /*+ NO_UNNEST */ manager_id from departments);

explain plan for

select *

from employees

where employee_id in (select /*+ NO_UNNEST */ manager_id from departments);

select * from table(dbms_xplan.display);

--相关子查询的解嵌套转换

select outer.employee_id,

outer.last_name,

outer.salary,

outer.department_id

from employees outer

where outer.salary >

(select avg(inner.salary)

from employees

inner where inner.department_id = outer.department_id);

explain plan for

select outer.employee_id,

outer.last_name,

outer.salary,

outer.department_id

from employees outer

where outer.salary >

(select avg(inner.salary)

from employees

inner where inner.department_id = outer.department_id);

select * from table(dbms_xplan.display);

--相关列变成了联结条件而子查询的剩余部分用来生成内嵌视图

联结消除

--主外键表消除

select e.*

from employees e, departments d

where e.department_id = d.department_id;

explain plan for

select e.*

from employees e, departments d

where e.department_id = d.department_id;

select * from table(dbms_xplan.display);

departments表的联结是如何完全消除的,之所以能够消除,是因为departments表中没有任何一列出现在查询列表中。并且由于主-外键约束,使得对于employees表中的每一行,在departments表中最多有一行匹配的记录。

/*

外联结表消除 外联表确保employees表中的每一行在结果集中至少出现一次,在jobs.job_id列上的唯一健约束,确保了对于employees表中的

每一行,在jobs表中最多有一行与之相匹配。这两个属性保证了employees表中的每一行在结果集中出现并且仅出现一次。

*/

select e.first_name, e.last_name, e.job_id

from employees e, jobs j

where e.job_id = j.job_id(+);

explain plan for

select e.first_name, e.last_name, e.job_id

from employees e, jobs j

where e.job_id = j.job_id(+);

select * from table(dbms_xplan.display);

Note:

如果在查询的任何地方使用了联结键,则不支持联结消除。

如果主外键约束包含多个列,则不支持联结消除。

排序消除

--order by消除

select count(*)

from (select d.department_name

from departments d

where d.manager_id = 7

order by d.department_name);

explain plan for

select count(*)

from (select d.department_name

from departments d

where d.manager_id = 7

order by d.department_name);

select * from table(dbms_xplan.display);

--使用no_query_transformation提示,让优华器不要对查询进行移除排序的转换

select /*+ no_query_transformation */

count(*)

from (select d.department_name

from departments d

where d.manager_id = 7

order by d.department_name);

explain plan for

select /*+ no_query_transformation */

count(*)

from (select d.department_name

from departments d

where d.manager_id = 7

order by d.department_name);

select * from table(dbms_xplan.display);

谓词推进

--谓词推进

select e1.last_name, e1.salary, v.avg_salary

from employees e1,

(select department_id, avg(salary) avg_salary

from employees e2

group by department_id) v

where e1.department_id = v.department_id

and e1.salary > v.avg_salary

and e1.department_id = 60;

explain plan for

select e1.last_name, e1.salary, v.avg_salary

from employees e1,

(select department_id, avg(salary) avg_salary

from employees e2

group by department_id) v

where e1.department_id = v.department_id

and e1.salary > v.avg_salary

and e1.department_id = 60;

select * from table(dbms_xplan.display);

--rownum不仅会禁止谓词推进,而且也会禁止视图合并

select e1.last_name, e1.salary, v.avg_salary

from employees e1,

(select department_id, avg(salary) avg_salary

from employees e2

where rownum > 1 --rownum prohibits predicate pushing!

group by department_id) v

where e1.department_id = v.department_id

and e1.salary > v.avg_salary

and e1.department_id = 60;

explain plan for

select e1.last_name, e1.salary, v.avg_salary

from employees e1,

(select department_id, avg(salary) avg_salary

from employees e2

where rownum > 1 --rownum prohibits predicate pushing!

group by department_id) v

where e1.department_id = v.department_id

and e1.salary > v.avg_salary

and e1.department_id = 60;

select * from table(dbms_xplan.display);

使用物化视图重写查询

--准备测试数据

drop table sales;

create table sales(

channel_id number,

promo_id number,

cust_id number,

amount_sold number,

time_id number,

prod_id number

);

drop table products;

create table products(

prod_id number,

prod_name varchar2(20)

);

drop table times;

create table times(

time_id number,

week_ending_day number

);

insert into products values(1,'衣服');

insert into products values(2,'鞋子');

insert into products values(3,'裤子');

insert into times values(1,1);

insert into times values(2,3);

insert into times values(3,5);

insert into sales values(1,1,1000,500,1,1);

insert into sales values(1,1,1000,500,2,2);

insert into sales values(1,1,1000,500,3,3);

insert into sales values(1,1,1000,500,1,3);

insert into sales values(1,1,1000,500,2,2);

--使用物化视图进行查询重写

select p.prod_id,

p.prod_name,

t.time_id,

t.week_ending_day,

s.channel_id,

s.promo_id,

s.cust_id,

s.amount_sold

from sales s, products p, times t

where s.time_id = t.time_id

and s.prod_id = p.prod_id;

explain plan for

select p.prod_id,

p.prod_name,

t.time_id,

t.week_ending_day,

s.channel_id,

s.promo_id,

s.cust_id,

s.amount_sold

from sales s, products p, times t

where s.time_id = t.time_id

and s.prod_id = p.prod_id;

select * from table(dbms_xplan.display);

create materialized view sales_time_product_mv

enable query rewrite as

select p.prod_id,

p.prod_name,

t.time_id,

t.week_ending_day,

s.channel_id,

s.promo_id,

s.cust_id,

s.amount_sold

from sales s, products p, times t

where s.time_id = t.time_id

and s.prod_id = p.prod_id;

select /*+ rewrite(sales_time_product_mv) */

p.prod_id,

p.prod_name,

t.time_id,

t.week_ending_day,

s.channel_id,

s.promo_id,

s.cust_id,

s.amount_sold

from sales s, products p, times t

where s.time_id = t.time_id

and s.prod_id = p.prod_id;

--rewrite提示来打开查询重写转换

--通过guery-rewrite_enabled参数默认启用的

explain plan for

select /*+ rewrite(sales_time_product_mv) */

p.prod_id,

p.prod_name,

t.time_id,

t.week_ending_day,

s.channel_id,

s.promo_id,

s.cust_id,

s.amount_sold

from sales s, products p, times t

where s.time_id = t.time_id

and s.prod_id = p.prod_id;

select * from table(dbms_xplan.display);

当发生硬解析时,oracle将会确定哪个计划对于该查询是最优的。就是oracle访问查询所使用的对象并返回相应结果数据将会采用的一系列步骤。

统计信息包括针对对象如表和索引收集统计信息,系统统计信息。

优化器是oracle内核中的代码路径,负责为查询确定最佳执行计划(使用统计信息)。

执行一个SQL查询,解析,绑定,执行,提取的步骤。

一次fetch调用将会访问缓冲区缓存中的一个或多个数据块。每次访问一个数据块时,oracle都会从该块中取出数据行然后在一次回路中返回给客户端。一次返回的行数是可配置的。

SQL*Plus 默认为15, 通过 set arraysize n来更改

jdbc 默认为10, 通过 ((OracleConnection)conn).setDefaultRowPrefetch(n)来更改。

列大小是如影响逻辑读取的

SQL> set arraysize 5

SQL> select * from employees;

已选择9行。

统计信息

----------------------------------------------------------

0 recursive calls

0 db block gets

9 consistent gets

0 physical reads

0 redo size

1282 bytes sent via SQL*Net to client

427 bytes received via SQL*Net from client

3 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

9 rows processed

SQL> set arraysize 15

SQL> select * from employees;

已选择9行。

统计信息

----------------------------------------------------------

0 recursive calls

0 db block gets

8 consistent gets

0 physical reads

0 redo size

1152 bytes sent via SQL*Net to client

416 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

9 rows processed

SQL> set arraysize 45

SQL> select * from employees;

已选择9行。

统计信息

----------------------------------------------------------

0 recursive calls

0 db block gets

8 consistent gets

0 physical reads

0 redo size

1152 bytes sent via SQL*Net to client

416 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

9 rows processed

SQL语句执行时的步骤汇总

Reference:

Oracle Concepts Guide

oracle+sql+groupby,oracle学习笔记2:SQL执行相关推荐

  1. SQL Server 2012学习笔记 (三) ----- SQL Server SQL语句

      在很多情况下,可以用CREATE TABLE语句创建数据表.使用ALTER TABLE语句修改表结构.使用DROP TABLE语句删除表:   可以使用CREATE DATABASE创建数据库.A ...

  2. oracle数据库基础知识总结,oracle数据库基础知识学习笔记

    oracle数据库基础知识学习笔记 一.oracle数据库类型: Char:  字符型(最大长度2000,定长.不足时以空格补充) Varchar2:字符型 最大长度 4000,变长,实际长度由存储的 ...

  3. SQL数据库教程-学习笔记2

    SQL数据库教程-学习笔记2 文章目录 SQL数据库教程-学习笔记2 三.DML语言的学习 1.插入语句:insert into 2.修改语句:update 3.删除语句:delete 4.练习题 四 ...

  4. SQL零基础学习笔记(一)

    真的不知道我写了这么多不同的的学习笔记又没用..开始SQL零基础学习笔记 百度百科:SQL(Structured Query Language)结构化查询语言,是一种数据库查询和程序设计语言,用于存取 ...

  5. vb.net调用oracle存储过程,vbnet2008连接oracle增删改查学习笔记(经典crud_含存储过程).doc...

    vbnet2008连接oracle增删改查学习笔记(经典crud_含存储过程).doc 我的VBNETORACLE增删改查学习笔记(本源码在VBNET2008下测试通过)学习VBNET有一段时间了,之 ...

  6. SQL学习笔记 | 02 SQL语句结构

    SQL学习笔记 | 02 SQL语句结构 一.表的导入 1.表的命名 2.导入步骤 3.导入需注意 二.标准SQL语法 1.语句结构 2.数据表的其他关键词 3.SQL语句的分类 一.表的导入 1.表 ...

  7. [python教程入门学习]python学习笔记(CMD执行文件并传入参数)

    本文章向大家介绍python学习笔记(CMD执行文件并传入参数),主要包括python学习笔记(CMD执行文件并传入参数)使用实例.应用技巧.基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋 ...

  8. oracle数据库开多线程,学习笔记:Oracle表数据导入 DBA常用单线程插入 多线程插入 sql loader三种表数据导入案例...

    天萃荷净 oracle之数据导入,汇总开发DBA在向表中导入大量数据的案例,如:单线程向数据库中插入数据,多线程向数据表中插入数据,使用sql loader数据表中导入数据案例 1.Oracle数据库 ...

  9. oracle 最大值及其_学习笔记:Oracle优化 SQL查询最大值 最小值时的优化方法案例...

    天萃荷净 select max(id),min(id) from table优化,分享开发DBA需求,在SQL语句查询最大值.最小值数据时的优化方式案例 1.查看数据库版本 SQL> selec ...

  10. Oracle PL/SQL语句基础学习笔记(上)

    PL/SQL是ORACLE对标准数据库语言的扩展,ORACLE公司已经将PL/SQL整合到ORACLE 服务器和其他工具中了,近几年中更多的开发人员和DBA开始使用PL/SQL,本文将讲述PL/SQL ...

最新文章

  1. 《jQuery EasyUI开发指南》——10.4 迭代开发
  2. android初学之退出应用程序
  3. PHP——MySQL数据库分页查询
  4. python中 普通方法_python中普通方法classmethod和staticmethod的区别与用法
  5. obs噪音抑制调多少合适_TVS瞬态抑制二极管的特性及应用
  6. Windows 2000缓冲区溢出技术原理
  7. matlab传函零极点形式,2013实验一 MATLAB 中控制系统模型的建立与仿真
  8. github出现Your account has been flagged.导致账号无法公开的解决办法
  9. shell脚本的作用
  10. SQL语句性能分析常用命令
  11. 多校 HDU 6313 Hack It——构造
  12. oracle将字符串转成数组_【算法打卡】上升下降字符串
  13. 损失函数——交叉熵损失函数应用(手把手教你计算损失函数)
  14. Java日志设计实践(1) - 常见问题
  15. 文献阅读1:Deep Learning for Image Super-resolution: A Survey
  16. LG V10距离感应器失效后的解决办法
  17. 网站地图是什么,怎么制作和查看网站的地图呢?
  18. 适合前端学习的几个网站
  19. 程序猿的世界~~~~
  20. Python中的XML解析错误[Et.parse(xml) ‘gbk‘ codec can‘t decode byte]分析与解决

热门文章

  1. 学习MIT 6.824 部分笔记
  2. ECS云服务器详细配置
  3. 成功项目经理的能力提升
  4. 小米笔记本U盘win10换win7系统操作教程
  5. PCB Windows Petya(永恒之蓝)勒索病毒补丁检测代码
  6. matlab 矩阵 对称,如何使用Matlab产生对称矩阵
  7. android 录屏工具,Android截屏、录屏工具
  8. 酷派系列手机root后怎么恢复文件
  9. redis连接异常 redis.clients.jedis.exceptions.JedisClusterException CLUSTERDOWN The cluster is down
  10. Linux(四):什么是Bash、什么是shell?