Tag Archives: Blog

Oracle优化神技之临时表

Oracle临时表在处理临时数据、会话数据隔离和复杂查询优化方面非常有用。 其底层逻辑是通过Oracle特殊的临时表来减少I/O操作和日志开销,提高了数据库性能和查询效率。开发者可以根据具体需求和场景,合理使用临时表来简化数据处理逻辑和提高系统性能。 早期开发人员在使用Oracle数据库时,经常因为不熟悉或不了解全局临时表(Global Temporary Table,下文简称GTT)的特性,因而自行定义了所谓的“临时表”,不但增加了开发复杂度,比如需要自行做数据清理和会话隔离等问题,还因高频操作这类表产生了大量重做日志(redo logs),进而增加了I/O负载和系统开销,主要代价这么多,最终的应用性能还不够好。 所幸这类问题随着用户量的提升,大家口口相传这个最佳实践,后续开发已经很少会犯这类低级问题。 那是不是用了Oracle的临时表就可以高枕无忧了呢? 最近笔者在某客户遇到一个临时表的问题,在分析这个客户问题的过程,也和大家一起来回顾下有关Oracle临时表的知识。 1.创建临时表 2.临时表统计信息 3.临时表索引 4.临时表是否cache 5.临时表相关问题 1.创建临时表 本次遇到问题的临时表,是使用的Oracle的GTT,且定义表中数据是基于session-specific的类型,脱敏后的创建语句为: CREATE GLOBAL TEMPORARY TABLE “JINGYU”.”G_T_T1″ (“ID” NUMBER(10,0) NOT NULL ENABLE, “NAME” VARCHAR2(30) NOT NULL ENABLE) ON COMMIT PRESERVE ROWS; 下面是官方文档截图,比较了GTT和PTT的差异: 除了上面提到的命名规则等差异之外,还要补充一点: GTT是8i后就已经支持的技术,而PTT要在18c及以后版本才支持。 关于GTT的两种类型,文档说明如下: 根据你的应用需求选择,简单说就是如果想在事务结束就清空表,选择DELETE … Continue reading

Posted in Oracle性能优化 | Tagged | Comments Off on Oracle优化神技之临时表

难道AI不知道tnsnames.ora的instance_name配置吗?

事情是这样,给某客户培训构建hands-on实验环境时,因测试环境有限,在同一环境做了一套ADG环境; 数据库是单实例,版本19.21,使用了多租户选件; 其中一个测试的PDB,名为demo1,其中建好测试用户jingyu,遇到的问题是: 使用sqlplus连接时,会随机连接到主库或者备库。 排查定位也很简单,因为这样的环境,监听lsnrctl status可以看到对应的服务下,是存在两个实例的,一个是主库,一个是ADG备库,但是,修改配置tnsnames.ora时,指定具体实例的语法怎么写,AI误导我走了弯路。 监听服务如下: Service “demo1.sub00000000000.xxvcn.xxxxxxvcn.com” has 2 instance(s). Instance “DB0913”, status READY, has 1 handler(s) for this service… Instance “DB0913_DG”, status READY, has 1 handler(s) for this service… tnsnames.ora配置如下: DEMO1 = (DESCRIPTION = (ADDRESS = (PROTOCOL … Continue reading

Posted in AI | Tagged | Comments Off on 难道AI不知道tnsnames.ora的instance_name配置吗?

同样的SQL,怎么突然就慢了?

本篇文章素材来源于某银行系统的一次性能问题分析。 许久没写这种troubleshooting类型的技术文章了,因为曾在服务公司呆过多年,工作原因,这方面之前做的多,听的更多,导致已经达到在自己认知维度下的一个小瓶颈,纯技术型的问题,稍微常见的基本都遇到过,非常少见的也基本是bug类(软件缺陷只能通过补丁或一些workaround的方式绕过去),感觉实在是没啥可写的。 另外注意,我这里说的“常见”指的是所有客户群中相对常见,而对单个具体客户而言,就非常可能从没有见过,这也是纯甲方技术人员(这里的纯甲方是指毕业就在一个甲方呆着,只能看到自己公司系统运行情况)的局限性,在早些年时,一些行业前辈们还会建议新的技术从业者即使想去甲方,也要先在乙方吃几年苦,能多见一些场景,再去甲方,这样会有比较准确的判断力,不至于轻易被乙方忽悠,也不会瞎挑毛病挑不到点子上让人鄙视。 前些日子有客户遇到问题,申请出差过去现场帮客户分析解决了,这个分析过程还是有些意思的,但最终结论简单来说就是DPR(直接路径读)问题,定位那一刻就觉得没啥可写的了,相关文章也太多了,今天突然想换个思路,看能否以故事线的方式来呈现这个问题,并解释所有技术细节,试图能够让所有人(包括技术小白)都能看得懂,所有用户相关信息均已做遮蔽处理。 首先你要忘掉这是个DPR的问题,让我们一起体会下这个分析问题的历程。 起初是被同事叫来帮忙一起分析客户问题,搞了一个微信群,客户先发了一些所谓异常时间的AWR、ASH、ADDM报告。 说明环境是普通X86服务器上的一套Oracle RAC数据库,版本是11.2.0.4,有应用补丁,触发BUG风险相对较低。嗯,还是要强调下,这里说的低只是说主观感觉上,因为11g已经摸爬滚打了那么多年,无数客户曾趟出的bug也都做了修复,遇到新bug的概率相对小而已,但并不是遇不到,一旦运气不好遇到就麻烦了,所以我们现在会强烈建议你升级到现有的LTS(长期支持版本)19c,可不要再用11g了。 这里提到非常有用的报告: AWR(Automatic Workload Repository) ASH(Active Session History) ADDM(Automatic Database Diagnostic Monitor) 其中ADDM相对用的少,它可以自动分析 AWR 中的性能数据,识别潜在的性能问题,并生成相应的建议报告。对于复杂问题可能不够准确,但至少也能给我们提供一个思路。 AWR可以记录某个时段下的真实负载情况,ASH可以在某个时段下看到是哪些会话在运行,非常好用,对等待事件的细致划分程度,也是其他数据库梦寐以求的东西。 和应用配合明确这个业务感知慢的SQL是否是AWR中显示的Top SQL,同时明确对应的具体sql_id,开始深入分析。 起初明确的sql_id,有一个对应的是一个存储过程,但此时没有进一步去查。 因为另外一个sql_id被认为更值得关注,这是一条简单的SQL,查询一个分区表,谓词条件只有一个定位到某一天的日期,该表是按月分区的。该SQL奇怪是正常的时候1分钟以内完成,异常的时候要接近10分钟完成,前者客户认为正常可接受,后者认为无法接受。 同样的SQL,查询不同日期,效率差距如此明显,另外客户反馈每天数据量基本相当,并没有数量级的差异。 此时最先想要排查的是是否有不同的执行计划? 可结果并不是,执行计划虽然是全表扫,但是前后并没有任何变化。 当时给的AWR中,我也看了IO部分,但只有3.3G的量级,感觉影响并不大,就忽略掉了。 后来去现场,实际动手分析发现,其实故障时刻远没有之前的AWR报告那样轻描淡写,重新收集后续故障时刻的AWR(1小时间隔)可以看到此时的DPR非常显著,达到了314G+,要是之前做紧急救援服务,看到这就已经结束了,直接凭借经验断定,DPR禁用掉再看效果。因为再慢的话,会影响其他客户问题的处理进度。 其实那种凭借历史经验直接判断问题虽然有很快很厉害的感觉,但却是不严谨的,现在我们要进一步确认细节,确认是否是这个问题。既然是DPR,再看TOP SQL中通过Reads的排序,发现Top 2都值得关注,因为物理读几千万,和后面SQL存在数量级上的差异: Top 1是一个存储过程,Top 2是一个SQL,经确认这个SQL也是存储过程之内的一条SQL,但是并不是之前我们分析的那条SQL,说明之前提供的方向有一定错误。这也说明这个Top 2才是问题根本。 同时配合ASH也可以看到的确就是这SQL引发的DPR,导致性能严重下降。 … Continue reading

Posted in Oracle性能优化, Oracle故障处理 | Tagged | Comments Off on 同样的SQL,怎么突然就慢了?