被Oracle全局临时表坑了

今天凌晨4点多钟,在客户现场的负责人打电话给我,说很奇怪,下载功能时快时慢。此下载功能非常复杂,之前一直是我优化,在半梦半醒中打开电脑,通过远程看着现场同事在PL/SQL developer中操作。执行同一条SQL,时快时慢,快的时候大概0.6s,慢的时候超过1分钟。

这条SQL有调用一个函数,功能是动态生成接近200条查询语句,SQL中都是有绑定变量的。是现场的测试环境,刚刚部署,心想应该不是数据库负载所致。

1. 抓取数据库AWR报告,完全没有压力,数据库服务器配置都是杠杠的。此刻心里有点乱,头一次遇到这种问题。现场9点钟要跟客户演示,此时已经快5点钟了。

2. 神器出场,打算用10046 trace定位到到底是那条SQL有问题,trace了多次,只有一次是慢的。期间也有插曲,现场不太会用sqlplus,交互化了很多时间。从众多的SQL中抽丝剥茧,终于定位到SQL,对比是:

SELECT DISTINCT D.ID, D.TABLE_NAME, DCT.COLUMN_NAME, GG.DATA_TYPE,

GG.TECHPARAM_NAME,DCT.SORT_NO FROM GG_CLASSIFY_TECHPARAM DCT, GG_TECHPARAM

GG, GG_CLASSIFY D, REL_OID_CLASSIFY T WHERE DCT.TECHPARAM_ID = GG.ID AND

D.ID = DCT.CLASSIFY_ID AND T.CLASSIFY_ID = D.ID

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        0      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2     61.00      61.04          0   25968917          0         156

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

total        3     61.00      61.04          0   25968917          0         156

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        0      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.80       0.81          0       32461         0         156

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

total        3      0.80       0.81          0       32461         0         156

3. 分析问题,第一感觉是SQL逻辑是否有问题,可惜10046里面没有trace到执行计划,不过看逻辑读,慢的那次应该是产生了笛卡尔积。经过简单的检查,SQL逻辑没有问题,人的第一感觉不一定靠谱。

4. 我在想是什么导致执行计划不准呢,猛然想起REL_OID_CLASSIFY是全局临时表,快速的想到一种可能,REL_OID_CLASSIFY的统计信息不准导致,通过user_tables查看这张表是没有统计信息的。那就是每次执行都动态采集啰,在Oracle
11g中执行autotrace,发现level=2,我想试试把动态采样的级别,说干就干。

SELECT /*+ dynamic_sampling(T 10) */DISTINCT D.ID, D.TABLE_NAME, DCT.COLUMN_NAME, GG.DATA_TYPE,

GG.TECHPARAM_NAME,DCT.SORT_NO FROM GG_CLASSIFY_TECHPARAM DCT, GG_TECHPARAM

GG, GG_CLASSIFY D, REL_OID_CLASSIFY T WHERE DCT.TECHPARAM_ID = GG.ID AND

D.ID = DCT.CLASSIFY_ID AND T.CLASSIFY_ID = D.ID;

发给开发人员,修改相关函数。增量后,多次测试后发现问题解决了。此时已经快7点了,天已经大亮,我有点倦意,但无法再次入睡。

       总结:对于这次临时表的问题,我想问题在于采样率低了以后造成的恶果。对于全局临时表要注意两点,一是要锁定临时表收集统计信息的功能,因为你收集的统计信息肯定是错的;二是使用它时最好是使用动态采用。学习知识,基础很重要。

时间: 2024-10-13 22:51:45

被Oracle全局临时表坑了的相关文章

一次被Oracle全局临时表坑的个人心得

[e良师益友网]使用Oracle开发的时候很多时候遇到一些你意想不到的问题,往往在于细节方面出现了不可回避的错误,下面分享一个难忘的事件,这次中表明基础方面的知识真的很重要 那 是凌晨4点多钟,在客户现场的负责人打电话给我,说很奇怪,下载功能时快时慢.此下载功能非常复杂,之前一直是我优化,在半梦半醒中打开电脑,通过远程看 着现场同事在PL/SQL developer中操作.执行同一条SQL,时快时慢,快的时候大概0.6s,慢的时候超过1分钟. 这条SQL有调用一个函数,功能是动态生成接近200条

oracle创建临时表

Oracle临时表可以说是提高数据库处理性能的好方法,在没有必要存储时,只存储在Oracle临时表空间中.希望本文能对大家有所帮助. 1 .前言 目前所有使用 Oracle 作为数据库支撑平台的应用,大部分数据量比较庞大的系统,即表的数据量一般情况下都是在百万级以上的数据量. 当然在 Oracle 中创建分区是一种不错的选择,但是当你发现你的应用有多张表关联的时候,并且这些表大部分都是比较庞大,而你关联的时候发现其中的某一张或者某几张表关联 之后得到的结果集非常小并且查询得到这个结果集的速度非常

SQL 临时表的使用,本地和全局临时表

一.SQL中创建本地临时表 方法1: CREATE TABLE #本地临时表名称 或 CREATE TABLE ##全局临时表名称 方法2: SELECT * INTO #本地临时表名称 FROM 表名称 SELECT * INTO ##全局临时表名称 FROM 表名称 说明: 1.临时表其实就是放在tempdb 中的的一个用户表. 2.本地临时表用"#"开头,全局临时表用"##"开头,这种表在会话期间存在,会话结束时自动删除. 二.删除临时表 语法: DROP T

sql server中的用户临时表和全局临时表的区别

临时表分为: 本地临时表,仅限于当前访问者访问,创建方法去如下:create table #TableName(表结构)储存于数据库tempdb内(硬盘),当前用户断开连接(把当前的),自动删除如果使用中不断开连接,且不需要该临时表请执行:drop table #TableName 全局临时表,所有访问用户访问,创建方法去如下:create table ##TableName(表结构)储存于数据库tempdb内,当所有访问用户断开连接,自动删除删除语句:drop table ##TableNam

oracle 创建临时表空间、用户表空间、创建用户关联表空间、授权等总结

1.创建临时表空间 CREATE TEMPORARY TABLESPACE test_temp TEMPFILE 'C:\oracle\product\10.1.0\oradata\orcl\test_temp01.dbf' SIZE 32M AUTOEXTEND ON NEXT 32M MAXSIZE 2048M EXTENT MANAGEMENT LOCAL; 一般从第二步开始就可以 2.创建用户表空间 CREATE TABLESPACE gzjssapce LOGGING DATAFILE

全局临时表

全局临时表是以两个‘##’符号为前缀,并且它对所有会话可见的一种临时表.全局临时表一般用在需要向所有人共享数据的时候使用.下面是一个全局临时表的示例. -- 全局临时表 IF OBJECT_ID('tempdb.dbo.##Globals','U') IS NOT NULL DROP TABLE dbo.##Globals; GO -- 创建全局临时表 CREATE TABLE dbo.##Globals ( ID INT NOT NULL, VALUE NVARCHAR(50) NOT NUL

Oracle 锁定临时表统计信息

全局临时表的统计信息是不能被收集的,如果被收集,它的统计信息肯定为0,会造成执行计划不准,所以要锁定它的统计信息,禁止系统自动收集. --先解锁表的统计信息,然后删除表的统计信息,最后锁住表的统计信息 declare v_sql varchar2(500); cursor rowList1 is select'begin dbms_stats.unlock_table_stats(user,''' || table_name || '''); end;' from user_tables s w

临时表和全局临时表

临时表就是那些名称以井号 (#) 开头的表.如果当用户断开连接时没有除去临时表,SQL Server 将自动除去临时表. 临时表不存储在当前数据库内,而是存储在系统数据库 tempdb 内. 全局临时表 以两个井号 (##) 开头的那些表名.在所有连接上都能看到全局临时表或者这样说只要这个全局临时表存在,那么用户创建会话后对所有的用户都是可见的.如果在创建全局临时表的连接断开前没有显式地除去这些表,那么只要所有其它任务停止引用它们,这些表即被除去.当创建全局临时表的连接断开后,新的任务不能再引用

数据库——创建局部临时表和全局临时表

局部临时表与全局临时表区别与示例: 1.局部临时表(#开头)只对当前连接有效,当前连接断开时自动删除. 2.全局临时表(##开头)对其它连接也有效,在当前连接和其他访问过它的连接都断开时自动删除. 3.不管局部临时表还是全局临时表,只要连接有访问权限,都可以用drop table #Tmp(或者drop table ##Tmp)来显式删除临时表. --create table #temp(num int primary key,pname varchar(20))//创建局部临时表,只对当前连接