侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

实例分析ORACLE数据库性能优化

数据库  /  管理员 发布于 6年前   269

ORACLE数据库的优化方式和MYSQL等很大的区别,今天通过一个ORACLE数据库实例从表格、数据等各个方便分析了如何进行ORACLE数据库的优化。

tsfree.sql视图

这个sql语句迅速的对每一个表空间中的空间总量与每一个表空间中可用的空间的总量进行比较

表空间是数据库的逻辑划分,一个表空间只能属于一个数据库。所有的数据库对象都存放在指定的表空间中。但主要存放的是表, 所以称作表空间。

SELECT FS.TABLESPACE_NAME "Talbspace",(DF.TOTALSPACE - FS.FREESPACE) "Userd MB",FS.FREESPACE "Free MB",DF.TOTALSPACE "Total MB",ROUND(100 * (FS.FREESPACE / DF.TOTALSPACE)) "Pct Free" FROM(SELECT TABLESPACE_NAME, ROUND(SUM(BYTES) / 1048576) TOTALSPACE FROMDBA_DATA_FILES GROUP BY TABLESPACE_NAME) DF,(SELECT TABLESPACE_NAME, ROUND(SUM(BYTES) / 1048576) FREESPACEFROM DBA_FREE_SPACEGROUP BY TABLESPACE_NAME) FS WHERE DF.TABLESPACE_NAME = FS.TABLESPACE_NAME;    

varray 表的使用

CREATE OR REPLACE TYPE EMPLOYER_NAME AS OBJECT (E_NAME VARCHAR(40));CREATE OR REPLACE TYPE PRIOR_EMPLOYER_NAME_ARR AS VARRAY(10) OF EMPLOYER_NAME;CREATE OR REPLACE TYPE FULL_MAILLING_ADRESS_TYPE AS OBJECT(STREET VARCHAR2(80), CITY VARCHAR2(80), STATE CHAR(2), ZIP VARCHAR2(10));CREATE OR REPLACE TYPE EMPLOYEE AS OBJECT(LAST_NAME VARCHAR(40), FULL_ADDRESS FULL_MAILLING_ADRESS_TYPE, PRIOR_EMPLOYERS PRIOR_EMPLOYER_NAME_ARR);CREATE TABLE EMP OF EMPLOYEE;INSERT INTO EMP VALUES('Jim', FULL_MAILLING_ADRESS_TYPE('Airplan Ave', 'Rocky', 'NC', '2343'), PRIOR_EMPLOYER_NAME_ARR(EMPLOYER_NAME('IBM'), EMPLOYER_NAME('APPLE'), EMPLOYER_NAME('CNN')));

-- 回滚

DROP TYPE PRIOR_EMPLOYER_NAME_ARR FORCE;
DROP TYPE FULL_MAILLING_ADRESS_TYPE FORCE;
DROP TYPE EMPLOYEE FORCE;
DROP TYPE EMPLOYER_NAME FORCE;
DROP TABLE EMP;
COMMIT;
SELECT P.LAST_NAME, PRIOR_EMPLOYERS.*
FROM EMP P, TABLE(P.PRIOR_EMPLOYERS) PRIOR_EMPLOYERS
WHERE P.LAST_NAME = 'Jim';

SQL 执行过程

1,检查安全性,确保sql数据执行者有权限执行
2,检查sql语法
3,可能发生的查询重新书写
4,执行

创建执行计划生产器接受经过解析的sql捆绑执行计划 执行执行计划 读取结果记录 排序结果集

数据访问方式:

1,全表扫描 db_file_multiblock_read_count = 128一次性最大读取block的数量Oracle开启并行: Alter table employee parallel degree 35; 顺序读取,直到结尾1,当表中不存在索引2,查询中不包含where字句3,内置函数中的索引无效4,like操作 %开头5,使用基于成本优化器 数据量少时6,当初始化文件中存在optimizer_mode = all_rows7,负向条件查询不能使用索引 例如 status != 0, not in, not exists 可以优化为 in (2,3);

下列情况的SQL语句会导致全表扫:

1,使用null条件查询导致全表扫,因为索引不能为空为了绕过全表扫这个问题,可以采取这样的方法 update emp set name = 'N/A' where name is null; select name from emp where name = 'N/A';2,对没有索引的字段查询,找到where条件后面的查询不带索引的字段,加索引可以大大提高查询性能。3,带有like条件的查询 like '%x%' 全表扫描,like 'x%' 不会全表扫,因为like以字符开始。4,内置的函数使索引无效,对于Date类型的数据来说非常的严重内置函数 (to_date,to_char)如果没有创建与内置函数匹配的基于函数的索引,那么这些函数通常会导致sql优化器全表扫描select name from emp where date < sysdate -8;检查where子句脚本是否含有 substr to_char decodeSELECT SQL_TEXT, DISK_READS, EXECUTIONS, PARSE_CALLSFROM V$SQLAREAWHERE LOWER(SQL_TEXT) LIKE '%substr%'OR LOWER(SQL_TEXT) LIKE '%to_char%'OR LOWER(SQL_TEXT) LIKE '%decode%'ORDER BY DISK_READS DESC;使用函数索引解决这个问题5,all_rows 优化器目标是提高吞吐量而且倾向于使用全表扫描,因此 对于任何一个要求sql快速查询返回部分结果集而言,optimizer_mode 应该设置为first_rows6,经验上,能过滤80%数据时就可以使用索引,对于订单状态,如果状态很少,不宜使用索引,如果状态值很多可以使用索引。7,如果查询字段大部分是单条数据查询,使用Hash索引性能更好原因:B-TREE 索引的时间复杂度是O(log(n))Hash 索引的时间复杂度是O(1)   8,符合索引最左前缀,例如建立符合索引(passWord,userName)select * from user u where u.pass_word = ? and u.user_name = ? 可以命中索引select * from user u where u.user_name = ? and u.pass_word= ? 可以命中索引select * from user u where u.pass_word = ? 可以命中索引select * from user u where u.user_name = ? 不可以命中索引 

如何找出影响力高的sql语句

 视图 v$sqlarea ,下列参数按照重要性从高到低排序 executions :越经常执行的sql语句就应当越早的调整,因为它会对整体的性能产生巨大的影响。 disk_reads: 磁盘读取,高的磁盘读取量可能表明查询导致过多的输入输出量。 rows_processed:记录处理,处理大量的记录的查询会导致较大的输入输出量,同时在排序的时候对TEMP表空间产生影响。 buffer_gets:缓冲区读取,高的缓冲读取量可能表明了一个高资源使用量的查询。 sorts:排序会导致速度的明显减低,尤其是在TEMP表空间中进行的排序。

2.赛列获取

Oracle对单表簇和多表簇进行散列存储,用来在连接操作中减低输入 输出

3,ROWID 访问

通过Rowid访问单条数据最快的方式,在实际的引用中,首先从索引中收集ROWID,然后通过ROWID进行数据读取

索引访问方式

索引都可以看做一组符合主键和ROWID的组合,索引访问的目的是收集对目标快速读取时所需要的ROWID

B树索引,位图索引 基于函数的索引.

索引范围扫描:读取一个或者多个ROWID 索引数值升序排列

eg:select * from table where a = 'a';

快速全索引扫描

eg: select distinct color,count(*) from table group by color;

单个索引扫描:读取一个单独的ROWID

降序索引范围扫描:读取一个或者多个ROWID 索引数值降序排列

AND - EQUALS: select * from table where a = 'a' and b > 34; 从where字句中收集多个ROWID

连接操作

嵌套循环连接

散列连接

散列连接通常快于嵌套循环连接,特别是在驱动表以及在查询的where子句中过滤,只剩下少量的记录的情况下

排序合并连接

连接提示:

表反向连接提示,例如,NOT IN, NOT EXISTS尽量避免使用 NOT IN 子句(它将调用子查询),而应该使用NOT EXISTS 子句(它将调用相关联的子查询),因为如果子查询返回的任何一条记录中包含空值,那么该查询将不会返回记录,如果允许NOT IN 子句查询为空,那么这种查询的性能非常的低,子查询会在外层查询块中对每一条记录重新执行一次。 

排序大小 sort_area_size_init.ora 参数,在控制台查看 sort_area_size;

查询语句:show parameter sort_area_size;

磁盘排序的执行速度要比内存排序的的执行速度慢14000倍

磁盘排序之所以昂贵,有以下几个原因:

1,同在内存中进行排序比较,速度太慢
2,磁盘排序耗费临时表空间的资源

数据库分配2个临时表空间:

select DEFAULT_TABLESPACE, TEMPORARY_TABLESPACE from dba_users where username='SYS';

select * from dba_temp_free_space;

Oracle临时表空间主要充当两个主要作用:临时表数据段分配和排序汇总溢出段。

排序汇总溢出的范围比较广泛。我们在SQL语句中进行order by/group by等操作,

首先是选择PGA的内存sort area、hash area和bitmap area。

如果SQL使用排序空间很高,单个server process对应的PGA不足以支撑排序要求的时候,临时表空间会充当排序段的数据写入。

而磁盘排序会降低单个任务的速度,同时还会影响Oracle实例中正在执行的其他任务,而且过多的磁盘排序将导致过多的空闲缓冲等待

以及将其他任务的数据块从缓冲池中分页出去的昂贵代价。

Oracle首先尝试在sort_area_size 分配的内存区中进行排序,Oracle只有不能再内存中排序时,才会调用磁盘排序
并将内存框架迁移到TEMP表空间,继续进行排序。

使用索引范围扫描的总体原则

 -- 对于原始排序的表, 仅读取少于40%的表记录查询就应该使用索引范围扫描,反之,多余40%,使用全表扫。 -- 对于未排序的表, 仅读取少于7%的表记录查询就应该使用索引范围扫描,反之,多余7%,使用全表扫。

表的访问方式

sql优化器

对于任何一个sql语句来说,存在唯一的优化表访问方式,而你的工作就是找到这种方式,并且长期使用它。

db_file_multiblock_read_count

目的是为sql语句生成最快 并且好资源最少的执行计划

1,基于规则的优化器

步骤 对于在where子句中的每一个表-- 生成一个可行的执行计划列表,这个列表中列出所有可以用来访问表的路径-- 为每一个执行计划指定级别数值-- 选择级别数值最低的计划-- 对结果集的选择级别最低 连接方法进行评估 基于规则优化器(PBO)特征- 总是使用索引,使用索引永远比使用全表扫描或使用排序合并连接(排序合并连接不需要索引)更加可取- 总是从驱动表开始 在from字句的最后一个表是驱动表,在这个表中选择的记录数应该是最少(查询返回值最少),RBO在执行嵌套循环连接操作时,将这个驱动表作为第一个操作表。- 只有在不可避免的情况下才使用全表扫描-任何索引都可以- 有时越简单越好 

2,基于成本的优化器(CBO)

 基于规则优化提供更加复杂的优化替代方案 ANALYZE TABLE TT_TCAS_HK_QTY COMPUTE STATISTICS; ANALYZE TABLE TT_TCAS_HK_QTY ESTIMATE STATISTICS SAMPLE 5000 ROWS; ANALYZE TABLE TT_TCAS_HK_QTY ESTIMATE STATISTICS SAMPLE 5000 ROWS FOR ALL INDEXED COLUMNS;  CBO在以下情况会选择错误的全表扫描 1,最高峰值过高 2,错误的optimizer_mode,如果optimizer_mode设置为all_rows,choose,那么sql优化器会倾向于使用全表扫描。 3,多表连接,存在多余3张表连接时,即使连接中存在索引,cbo仍然会对这些表进行全表扫描。 4,不平衡的索引分布,比如 color = 'blue' color字段上有索引,但是只有1%的记录属于blue,   

SQL 的SGA统计资料

select name,value from v$sysstat where name like 'table%'

table scans(short table) -- 对小表全表扫描的次数

table scans(long table) -- 对大表全表扫描的次数,评估是否通过加索引减少大表的扫描次数 或者通过调用Oracle并行(opq)来提高查询的执行速度。

table scans Rows Gotten -- 这个数目说明全表扫描扫描记录条数

table scans blocks Gotten -- 扫描获取数据库的数目

Table fetch by rowid -- 通过索引访问记录的数目,这里的索引通常是嵌套循环连接

table fetch by Continued Row -- 这个数目说明与其他数据块连接在一起的记录数目

程序库缓存中可以多次使用的SQL

Oracle在辨认"相同的"sql语句是存在问题

例如:select from customer; Select From Customer; 尽管区别字母的大小写,Oracle会对第二个sql语句进行重新编译执行;


  • 上一条:
    详解oracle分页查询的基础原理
    下一条:
    Oracle 中Contains 函数的用法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客