首页 > 数据库 >Oracle数据库统计信息_执行计划_sharedpool等的知识梳理

Oracle数据库统计信息_执行计划_sharedpool等的知识梳理

时间:2023-12-31 15:22:37浏览次数:46  
标签:sharedpool 数据库 索引 SQL Oracle 执行 统计

Oracle数据库统计信息_执行计划_sharedpool等的知识梳理


背景

最近有项目出现了年底业务量增加时卡顿的情况. 
同事多次发现执行SQL缓慢.
但是重新执行统计信息更新后问题就优化的现象.
12月份上半月解决测试环境的SQLServer卡顿时基本上也是这个套路
重建索引, 添加必要索引的方式进行优化. 
产品项目上的问题和优化手段也比较相似. 
这里想总结一下,数据库方面的知识,作为一个学习和提高的机会 

前期总结的执行计划,索引更新的SQL

## Oracle重新获取统计信息:
exec dbms_stats.gather_schema_stats(ownname =>'username',options => 'GATHER',estimate_percent => dbms_stats.auto_sample_size, method_opt => 'for all columns size repeat', degree => 4)
## Oracle 还可以这样:
select 'alter index '||index_name|| ' rebuild;' from user_indexes

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

## SQLSERVER重新新建所有表的索引:
EXEC SP_MSFOREACHTABLE 'dbcc DBreindex("?")'
## SQLSERVER重新收集所有表的统计分析记录.
EXEC SP_UPDATESTATS;

## 注意可以统计一下Oracle的执行统计信息更新的时间:
我这边一个 四路72核心144线程的服务器, 我这边执行的SQL为:
set timing on ;
exec dbms_stats.gather_schema_stats(ownname =>'xxxx',options => 'GATHER',estimate_percent => dbms_stats.auto_sample_size, method_opt => 'for all columns size repeat', degree => 72)

执行时间为: 
第一次的执行时间为: Elapsed: 00:28:10.46
直接进行第二次时为: Elapsed: 00:26:29.11
发现统计信息的时间跟 表大小/表多少/CPU/硬盘的情况相关性很大.
但是跟是否统计过的关系反而不是很大. 

注意 我一共有 20000个表, 数据文件大小为: 200G左右. 

CPU使用情况
02:10:01 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle
02:10:01 PM     all      1.89      0.00      3.42      0.04      0.00     94.65
02:20:01 PM     all      2.12      0.00     25.00      0.05      0.00     72.83
02:30:01 PM     all      2.27      0.00     20.92      0.17      0.00     76.64
02:40:01 PM     all      1.90      0.00     13.93      0.08      0.00     84.09

发现大部分时间都是 sys态的时间. 

前提-关于数据库的优化思路

Oracle.SQLServer等的大部分业务表都是堆表.
堆表的特性在插入删除时效率很快,查询时的性能不是很好 

大量进行写更新的表一半都建议使用堆表方式进行存储. 

堆表的性能的生命线其实是 索引. 
索引一方面可以绝对查询效率, 
另外一方面,如果索引可以包含被查询的内容和判断条件,产品是可以不用再range查询时执行 回表的操作, 性能会优化十倍百倍. 

其实不管是何种数据库, 优化思路其实都是:
0. 优化业务SQL, 避免出现不走索引, 全表查询, 胡乱关联,无限制关联, 深分页, 大表驱动小标, 无限循环, 不进行变量绑定, 大量业务单条提交等类型的SQL语句. 
1. 减少重点业务表的大小, 可以使用冷热数据分别存储, 分区表等方式来实现.
2. 增加索引的区分度, 以及有效性, 如果是分区表,所有的查询SQL建议必须第一个Where条件指定分区字段. 少量字段查询, 尽量使用复合索引覆盖查询结果集.
3. 适当进行索引.统计信息的更新, 避免CBO使用错误的查询分析计划, 导致执行效率下降.
4. 适当增加SGA/PGA等内存参数, 优化process/session/cursor等参数, 避免出现内存配置不对导致出现性能瓶颈
5. 优化操作系统参数, 保证操作系统没有其他大型IO影响实际业务使用, 避免非数据库因素影响数据库. 比如numa/透明大页/大页内存参数等.
6. 优化服务器硬件, 比如升级快速的硬盘, 换用更加优秀的Raid卡, 数据库坚决避免使用PM8222这种类型的无缓存的raid卡. 
7. 有条件使用高主频的CPU, 主频对高性能的影响要比核心数更加重要, 尽量选用较新的CPU, 新CPU的IPC更加优秀一些. 
8. 使用高性能的网络/最佳性能配置的BIOS,良好的散热,平稳的电源供电,没有震动的机房条件, 减少认为误操作的可能. 
9. 合理进行运维监控以及巡检, 保证数据库平稳运行. 

数据库的自动更新

Oracle数据库其实是有一个计划任务,定期进行数据库的索引统计信息更新的处理

可以进行如下的操作进行处理: 查看所有表的最后被分析的时间
select table_name, num_rows, last_analyzed from user_tables where num_rows is not null order by LAST_ANALYZED DESC  ;

Oracle数据库的计划任务一般可以使用如下方式查询
select * from dba_autotask_client
select * from dba_autotask_client_history  order by WINDOW_END_TIME DESC 

第一个SQL可以查看计划任务是否开启
第二个SQL可以查看所有任务执行情况. 开始时间,结束时间等. 

如果发现特定表的执行计划不够新.可以采用这个命令进行处理: 
call dbms_stats.gather_table_stats('用户名','表名');

注意事项

虽然有一个计划任务: auto optimizer stats collection
执行统计计划的分析
但是数据库并不是无脑的进行所有表的统计信息更新的. 

他一般是按照数据库的数据/索引变化的量进行评估, 是否进行统计信息的更新
这里如果表很大, 你的变化量虽然不小, 到那时比率如果非常低, 也有可能不会执行统计信息更新
所以就会出现一个很严重的悖论, 导致大表的性能很差, 却得不到应该有的优化. 

可以通过如下SQL进行查询表最近一周的变量话排名. 

SELECT
	obj.owner,
	obj.object_name,
	to_char( sn.BEGIN_INTERVAL_TIME, 'yyyy-mm-dd' ) start_day,
	round( sum( a.db_block_changes_delta * 8 ) / 1024 / 1024, 2 ) incr_GB 
FROM
	dba_hist_seg_stat a,
	dba_hist_snapshot sn,
	dba_objects obj 
WHERE
	sn.snap_id = a.snap_id 
	AND obj.object_id = a.obj# 
	AND obj.object_type = 'TABLE' 
	AND obj.owner NOT IN ( 'SYS', 'SYSTEM' ) 
	AND end_interval_time BETWEEN to_timestamp( SYSDATE - 10 ) 
	AND to_timestamp( SYSDATE ) 
GROUP BY
	obj.owner,
	obj.object_name,
	to_char( sn.BEGIN_INTERVAL_TIME, 'yyyy-mm-dd' ) 
ORDER BY
	INCR_GB DESC

关于统计信息和SQL执行

Oracle为了SQL的高效执行其实做了非常多的工作:

1. 不停地进行统计信息的更新和处理
2. 一直在不停地优化CBO分析器.
3. 一直在进行SQL执行效率的提升, 比如使用并行, 使用最新的类似于AVX512等指令集.
4. 将形成的合理的执行计划存储到 shared_pool 实现执行计划的 复用, 避免解析执行计划浪费CPU和浪费查询时的实际物理时间. 

这里面其实就存在一个比较严重的问题:

数据库存储的执行计划,可能空间不够被弃用,也有可能使用了一开始错误的统计信息, 导致执行效果并不好, 但是还一直存在未进行清理. 
现场遇到的问题, 其实是第二个. 

第一个问题,如果SQL数量居多, 但是shared_pool内存用量较小, 也会出现CPU使用量较高的问题. 

其实这两个问题 我们都可以理解为是内存使用不当 导致CPU利用率出现波动的情况. 

其实非常不建议生产时间进行 统计信息的收集, 和 shared_pool的清理工作. 此类工作应该都放到业务低谷期进行处理. 

应急处理的方法

第一个: 有条件重启的话, 重启数据库.
但是历久弥新的数据库非常不建议执行重启, 如果数据库处于一种很微妙的平衡状态, 
一次非规划内的重启可能会导致数据库宕机. 如果不是自己特别命硬, 不建议动不动就重启数据库. 尤其是高压力的情况下.

第二个: 清理内存
sqlplus / as sysdba <<EOS
alter system flush shared_pool ;
EOS
执行很简单, 但是如果高并发情况下, 重新生成统计信息可能会导致CPU瞬间升高.
当然了如果服务器CPU够猛可以不考虑, 如果是那种跟自己工龄还长的服务器CPU, 不建议挑战物理规律. 

第三个: 使用工具逐个清理
可能存在一些异常情况, 并且需要dba的权限,不是非常建议采用此类方式. 

后续优化思路

如果全表重建比较难, 是否可以再业务高峰之前的早上四点开始. 暂停一下计划任务.
留出大约 2-3个小时左右的时间, 执行一下统计任务的采集. 

这样可以保证第二天可以有比较准确的统计信息实用. 

另外中午如果没有备份恢复后者是其他计划任务的话
可以将业务使用量较大的表执行一下计划统计信息的收集. 
避免早上业务量较大引起统计信息失真. 

需要注意, SQL最好都进行一下限时操作, 避免业务跟业务高峰重合, 影响客户体验. 

标签:sharedpool,数据库,索引,SQL,Oracle,执行,统计
From: https://www.cnblogs.com/jinanxiaolaohu/p/17937529

相关文章

  • HBase 与 NoSQL 数据库对比:了解 HBase 在大数据领域的优势
    1.背景介绍HBase是一个分布式、可扩展、高性能的列式存储数据库,它是ApacheHadoop项目的一部分。HBase设计用于存储海量数据并提供低延迟、自动分区、数据备份和恢复等特性。HBase是一个NoSQL数据库,它与其他NoSQL数据库如Cassandra、MongoDB等有一定的相似性,但也有一些......
  • 向量内积在图数据库中的应用
    1.背景介绍图数据库(GraphDatabase)是一种特殊类型的数据库,它使用图形数据结构(GraphDataStructure)来存储、管理和查询数据。图数据库的核心概念是节点(Node)和边(Edge),节点表示数据实体,边表示关系。图数据库广泛应用于社交网络、知识图谱、地理信息系统等领域。向量内积(DotProduct)是......
  • Oracle19c on 银河麒麟的安装与升级
    Oracle19con银河麒麟的安装与升级下载内容preinstallCentOS8https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el8.x86_64.rpmpreinstallCentOS7https://yum.oracle.com/repo/OracleLinux/OL7/lates......
  • oracle11gR2表空间使用查询
    SELECTa.tablespace_name"表空间名称",100-ROUND((NVL(b.bytes_free,0)/a.bytes_alloc)*100,2)"占用率(%)",ROUND(a.bytes_alloc/1024/1024,2)"容量(M)",ROUND(NVL(b.bytes_free,0)/1024/1024,2)"空闲(M)",ROUND((a.bytes_alloc-NVL(b.byte......
  • openGauss学习笔记-179 openGauss 数据库运维-逻辑复制-发布订阅
    openGauss学习笔记-179openGauss数据库运维-逻辑复制-发布订阅发布和订阅基于逻辑复制实现,其中有一个或者更多订阅者订阅一个发布者节点上的一个或者更多发布。订阅者从它们所订阅的发布拉取数据。发布者上的更改会被实时发送给订阅者。订阅者以与发布者相同的顺序应用那些数据......
  • openGauss学习笔记-180 openGauss 数据库运维-升级-升级前必读
    openGauss学习笔记-180openGauss数据库运维-升级-升级前必读180.1升级方案本节为指导用户选择升级方式。用户根据openGauss提供的新特性和数据库现状,确定是否对现有系统进行升级。当前支持的升级模式为就地升级、灰度升级和滚动升级。升级方式的策略又分为大版本升级和小版......
  • oracle 11g分区表相关知识
    文档课题:oracle11g分区表相关知识.数据库:oracle11.2.0.41、相关知识表分区指允许用户将一个表分成多个分区,用户可以只访问表中的特定分区.可以将不同的分区存储在不同的磁盘,提高访问性能和安全性,可以独立地备份和恢复每个分区.主要有范围分区、散列分区、列表分区、复合分区.......
  • 数据库查询,按年月排序,计算每月、当年每月有几条数据
    数据库查询,按年月排序,计算每月有几条数据  数据库查询,按年月排序,计算当年每月有几条数据SELECTDATE_FORMAT(inspection_date,'%Y-%m')ASDATETIME,count(*)ASnumFROMgw_inspection_datat1WHEREYEAR(inspection_date)=YEAR(CURDATE())GROUPBY......
  • 在 Flask 中使用数据库 允许我们使用面向对象的方式来操作数据库 Flask 中使用表单的
    在Flask中使用数据库,你可以使用ORM(对象关系映射)技术,它允许我们使用面向对象的方式来操作数据库,而不需要直接编写SQL语句¹。以下是一些基本步骤:安装依赖:首先,我们需要安装Flask和ORM库的依赖。Flask提供了多个ORM库的选择,例如SQLAlchemy、Peewee和SQLObject等。在这......
  • 基于JFinal的数据库配置
    参考——https://blog.csdn.net/weixin_42579328/article/details/89490760 1、创建数据表:CREATETABLE`user`(`id`int(11)NOTNULLAUTO_INCREMENT,`name`varchar(20)NOTNULL,`pwd`varchar(20)NOTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=......