白亿条数据量的Oracle数据库如何优化?

简介: 白亿条数据量的Oracle数据库如何优化?

一、导读


一个好的运维团队,应该首先是一批好的开发工程师,当软件系统变得越来越复杂时 ,主动承担起架构调整,系统调优,自动化等工作来帮助降低系统复杂度,优化系统 架构,提高系统可用性,下图为Oracle优化的进化论。

ec94fdb31dbe4946bc8537a4c7a712cd.jpg


二、优化常识



2.1.显示执行计划方法


SYS@ORCL> SET AUTOTRACE TRACEONLY:只显示统计结果,不显示返回的结果集合
• 1


2.2.SQL执行计划


ed023329e797494ab3d2e5e5b9a7ffdc.png

执行计划:一条查询语句在ORACLE中的执行过程或访问路径的描述。
即就是对一个查询任务,做出一份怎样去完成任务的详细方案。
如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,
看看SQL的每一步执行是否存在问题。
看懂执行计划也就成了SQL优化的先决条件。 
通过执行计划定位性能问题,定位后就通过建立索引、修改sql等解决问题。
2.2.1 执行顺序的原则
执行顺序的原则是:由上至下,从右向左
由上至下:在执行计划中一般含有多个节点,
相同级别(或并列)的节点,靠上的优先执行,靠下的后执行
从右向左:在某个节点下还存在多个子节点,先从最靠右的子节点开始执行。
2.2.2 执行计划中字段解释
ID: 一个序号,但不是执行的先后顺序。执行的先后根据缩进来判断。
Operation: 当前操作的内容。
Rows: 当前操作的Cardinality,Oracle估计当前操作的返回结果集。
Cost(CPU):Oracle 计算出来的一个数值(代价),用于说明SQL执行的代价。
Time:Oracle 估计当前操作的时间。
在看执行计划的时候,除了看执行计划本身,
还需要看谓词和统计信息。 通过整体信息来判断SQL效率。
2.2.3 谓词说明
Access :
* 通过某种方式定位了需要的数据,然后读取出这些结果集,叫做Access。
* 表示这个谓词条件的值将会影响数据的访问路劲(表还是索引)。
Filter:
* 把所有的数据都访问了,然后过滤掉不需要的数据,这种方式叫做filter 。
* 表示谓词条件的值不会影响数据的访问路劲,只起过滤的作用。
在谓词中主要注意access,要考虑谓词的条件,使用的访问路径是否正确。

2.3 Statistics统计信息


CBO包含以下组件:查询转换器、评估器、计划生成器
recursive calls:产生的递归sql调用的条数。
Db block gets:从buffer cache中读取的block的数量
consistent gets:从buffer cache中读取的undo数据的block的数量   
physical reads:从磁盘读取的block的数量  
redo size:DML生成的redo的大小   
bytes sent via SQL*Net to client:
数据库服务器通过SQL*Net向查询客户端发送的查询结果字节数
bytes received via SQL*Net from client:
通过SQL*Net接受的来自客户端的数据字节数
SQL*Net roundtrips to/from client:
服务器和客户端来回往返通信的Oracle Net messages条数
sorts (memory):在内存执行的排序量   
sorts (disk):在磁盘上执行的排序量
rows processed:处理的数据的行数


0cb2dbbef7934b61b2ba67d0bec2d8ac.png

2.4 表连接方式


在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式
多表之间的连接有三种方式:
Nested Loops,Hash Join 和 Sort Merge Join.
具体适用哪种类型的连接取决于:
* 当前的优化器模式 (ALL_ROWS 和 RULE)
* 取决于表大小
* 取决于连接列是否有索引
* 取决于连接列是否排序
2.4.1 hash join
使用情况:Hash join在两个表的数据量差别很大的时候.(小表一般会丢在内存中)
2.4.2 merge join
Merge Join 是先将关联表的关联列各自做排序,然后从各自的排序表中抽取数据,
到另一个排序表中做匹配。
适用情况:
1.RBO模式
2.不等价关联(>,<,>=,<=,<>)
3.HASH_JOIN_ENABLED=false
4. 用在没有索引,并且数据已经排序的情况.
2.4.3 nested loop
    Nested loops 工作方式是循环从一张表中读取数据(驱动表outer table),
    然后访问另一张表(被查找表 inner table,通常有索引)。
    驱动表中的每一行与inner表中的相应记录JOIN。类似一个嵌套的循环。
适用情况:
适用于驱动表的记录集比较小(<10000)而且inner表需要有有效的访问方法(Index),
并且索引选择性较好的时候.
JOIN的顺序很重要,驱动表的记录集一定要小,返回结果集的响应时间是最快的。

a49281b08c894bba963431128c3d8051.png

2.4.执行计划的获取


2.4.1 dbms_xplan.display_cursor获取
select * from table( dbms_xplan.display_cursor('&sql_id') );    
--该方法是从共享池得到,如果SQL已被age out出share pool,则查找不到
select * from table( dbms_xplan.display_awr('&sql_id') ); 
 --该方法是从awr性能视图里面获取(直接在命令窗口执行,可对比执行计划,真实的计划)
2.4.2 Explain Plan(预估执行计划)
SYS@ORCL> explain plan for select * from scott.emp;
SYS@ORCL> select * from table(dbms_xplan.display);
注:Explain plan只生成执行计划,并不会真正执行SQL语句,
因此产生的执行计划有可能不准


三、优化案例展示



3.1 未走索引


创建测试表:
SQL> create table system.test_objects as select * from dba_objects;
SYS@ORCL> insert into system.test_objects select * from system.test_objects;  --数据量达到1200多万即可
收集统计信息:
SQL> EXEC DBMS_STATS.gather_table_stats('SYSTEM','TEST_OBJECTS');
SQL> set autotrace on
SQL> set linesize 200
SYS@ORCL> set time on timing on
SQL> select count(*)  from system.test_objects A  where object_name='OBJ$';
  COUNT(*)
----------
       256
Elapsed: 00:00:03.08
Execution Plan
----------------------------------------------------------
Plan hash value: 3799704240
-----------------------------------------------------------------------------------
| Id  | Operation          | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |              |     1 |    25 | 19506   (2)| 00:03:55 |
|   1 |  SORT AGGREGATE    |              |     1 |    25 |            |          |
|*  2 |   TABLE ACCESS FULL| TEST_OBJECTS |   226 |  5650 | 19506   (2)| 00:03:55 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("OBJECT_NAME"='OBJ$')
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
     176155  consistent gets
     149912  physical reads
          0  redo size
        516  bytes sent via SQL*Net to client
        469  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SYS@ORCL> set autotrace off
SYS@ORCL> select count(*)  from system.test_objects;


3.2 如何优化


 如前所示,原SQL是要统计表system.test_objects中,object_name列中,
 值为'OBJ$'的记录的行数。而表system.test_objects中共有记录600余万行。
 该SQL共执行了3秒,进行了约17万个逻辑读(从内存中读取数据)
 和几乎同样数量的物理读(从外部存储上读取数据,其处理速度比内存的处理速度慢千倍以上)。
 但实际上,只有256行记录是满足检索条件的,其相对于600余万行的总记录数而言,是非常少的。
 同时,也说明OBJECT_NAME列上选择性是比较好的。
      综上,我们可以考虑在列OBJECT_NAME列上创建索引,这样,当进行同样的SQL时:
       第一,我们可以通过该索引快速定位到满足条件的行,
       从而避免了从头扫到尾的全表扫描的处理方式。
       第二,由于是统计满足相关条件的记录数量,
       所以,并不需要返回除检索条件列之外的其它列,只是计数罢了,
       所以,仅仅访问相关的索引就足够了,而不需要再从索引回表,去获取其它列。
##优化效果
在列object_name创建索引后,执行时间为,由之前的03.08表降为0.01秒,
辑读和物理读分别为5和4
创建索引
SQL> create index ind_test_objects_object_name on system.TEST_OBJECTS(Object_Name);
SQL> select count(*)  from system.test_objects A  where object_name='OBJ$';
  COUNT(*)
----------
       256
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 251147837
--------------------------------------------------------------------------------------------------
| Id  | Operation         | Name                         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                              |     1 |    25 |     6   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |                              |     1 |    25 |            |          |
|*  2 |   INDEX RANGE SCAN| IND_TEST_OBJECTS_OBJECT_NAME |   226 |  5650 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_NAME"='OBJ$')
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          4  consistent gets
          3  physical reads
          0  redo size
        516  bytes sent via SQL*Net to client
        469  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
目录
相关文章
|
23天前
|
存储 Oracle 关系型数据库
数据库数据恢复—ORACLE常见故障的数据恢复方案
Oracle数据库常见故障表现: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE ASM存储破坏。 3、ORACLE数据文件丢失。 4、ORACLE数据文件部分损坏。 5、ORACLE DUMP文件损坏。
75 11
|
2月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
2月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
29天前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。
|
2月前
|
SQL Oracle 关系型数据库
Oracle数据库优化方法
【10月更文挑战第25天】Oracle数据库优化方法
57 7
|
11天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
38 3
|
11天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
38 3
|
11天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
52 2
|
24天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
168 15
|
17天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。

推荐镜像

更多