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 ROWS类型;如果想在会话结束才清空表,就选择PRESERVE ROWS类型。

2.临时表统计信息

临时表也是有统计信息的,而且临时表统计信息的机制在不同版本也有差异。

先看下在19c版本下表现:

我先在session1中插入两条测试数据,收集统计信息:

INSERT INTO G_T_T1 VALUES (1, 'Alfred');
INSERT INTO G_T_T1 VALUES (2, 'Mcdull'); BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'JINGYU',
tabname => 'G_T_T1',
cascade => TRUE
);
END;
/ SELECT owner, table_name, num_rows, blocks, empty_blocks, avg_space
FROM dba_tab_statistics
WHERE table_name = 'G_T_T1';

紧接着在session2中插入一条数据,收集统计信息:

INSERT INTO G_T_T1 VALUES (3, 'Test');

BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'JINGYU',
tabname => 'G_T_T1',
cascade => TRUE
);
END;
/ SELECT owner, table_name, num_rows, blocks, empty_blocks, avg_space
FROM dba_tab_statistics
WHERE table_name = 'G_T_T1';

两个查询结果是不一样的,两行结果,分别显示为2条和1条数据的统计信息。

--result1:

08:52:42 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> SELECT owner, table_name, num_rows, blocks, empty_blocks, avg_space
FROM dba_tab_statistics
WHERE table_name = 'G_T_T1';08:53:39 2 08:53:39 3 OWNER TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE
------------------------------ ------------------------------ ---------- ---------- ------------ ----------
JINGYU G_T_T1
JINGYU G_T_T1 2 1 0 0 Elapsed: 00:00:00.02

--result2:

08:53:35 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> SELECT owner, table_name, num_rows, blocks, empty_blocks, avg_space
FROM dba_tab_statistics
WHERE table_name = 'G_T_T1';08:53:44 2 08:53:44 3 OWNER TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE
------------------------------ ------------------------------ ---------- ---------- ------------ ----------
JINGYU G_T_T1
JINGYU G_T_T1 1 1 0 0 Elapsed: 00:00:00.01

这说明全局临时表在19c版本的默认统计信息是session级别。

--查看全局临时表的统计信息首选项设置
SELECT DBMS_STATS.GET_PREFS('GLOBAL_TEMP_TABLE_STATS', 'JINGYU', 'G_T_T1') AS global_temp_table_stats
FROM dual; 09:04:59 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> --查看全局临时表的统计信息首选项设置
SELECT DBMS_STATS.GET_PREFS('GLOBAL_TEMP_TABLE_STATS', 'JINGYU', 'G_T_T1') AS global_temp_table_stats
FROM dual;
09:05:00 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> 09:05:00 2
GLOBAL_TEMP_TABLE_STATS
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SESSION Elapsed: 00:00:00.01

具体查了下文档,说是在Oracle 12c及之后的版本中,全局临时表(GTT)的统计信息确实有可能是会话级别的。这意味着每个会话可以有自己的统计信息,这与全局共享的统计信息不同。

Default in 12c is now SESSION global temporary table statistics.  Consider whether your database application depends on SHARED global temporary table statistics.

而如果你的数据库还是11g版本,那么这个统计信息的机制就是不同的,也就是SHARED,这里模拟将19c的这个也修改为SHARED模式,看看表现:

BEGIN
DBMS_STATS.SET_TABLE_PREFS(
ownname => 'JINGYU',
tabname => 'G_T_T1',
pname => 'GLOBAL_TEMP_TABLE_STATS',
pvalue => 'SHARED'
);
END;
/ BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'JINGYU',
tabname => 'G_T_T1',
cascade => TRUE
);
END;
/

成功修改为shared后,当表中有3条数据时收集统计信息后再次查询,会发现这个统计信息在其他会话也可以访问到:

09:10:46 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> r
1 SELECT owner, table_name, num_rows, blocks, empty_blocks, avg_space
2 FROM dba_tab_statistics
3* WHERE table_name = 'G_T_T1' OWNER TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE
------------------------------ ------------------------------ ---------- ---------- ------------ ----------
JINGYU G_T_T1 3 1 0 0 Elapsed: 00:00:00.02
09:10:48 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1>

3.临时表索引

GTT是可以创建索引的,当然这个索引也是临时的属性,另外还可以在GTT上创建视图和触发器。

You can create indexes for global (not private) temporary tables with the CREATE INDEX
statement. These indexes are also temporary. The data in the index has the same
session or transaction scope as the data in the temporary table. You can also create a
view or trigger on a global temporary table.

4.临时表是否cache

使用ALTER TABLE ... CACHE可以提高GTT查询性能。

ALTER TABLE G_T_T1 CACHE;

在Oracle中,通过使用ALTER TABLE ... CACHE语句可以在创建GTT时指定缓存属性。GTT是一种特殊类型的数据库表,用于存储临时数据,数据在会话结束或事务完成时被清除。CACHE关键字在这里的作用是指定GTT的缓存属性。

具体来说,CACHE关键字指示Oracle数据库将GTT的数据块缓存在内存中,而不是直接写入磁盘。这样做的好处是可以提高查询临时表数据的性能,因为访问内存通常比访问磁盘要快得多。

需要注意的是,使用CACHE会占用更多的内存空间,因为临时表的数据在会话结束或事务完成后会被清除,所以对于大型数据量或长时间运行的会话,可能需要权衡内存利用和性能。

临时表是否设置了CACHE属性是可以通过dbms_metadata.get_ddl中看到cache标识的:

select dbms_metadata.get_ddl('TABLE','G_T_T1','JINGYU') from dual;

  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
CACHE

特别需要注意的是,这个简单的cache命令,在线直接执行很可能会失败:

alter table G_T_T1 cache;

会报错ORA-14450:

14:46:14 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> alter table G_T_T1 cache;
alter table G_T_T1 cache
*
ERROR at line 1:
ORA-14450: attempt to access a transactional temp table already in use Elapsed: 00:00:00.02

这是因为有会话在使用GTT,确保没有使用的会话重新执行才能成功:

14:51:14 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO1> alter table G_T_T1 cache;

Table altered.

Elapsed: 00:00:00.10

5.临时表相关问题

顺便查了一些相关问题,作为扩展供大家学习参考:

FYI:

Oracle优化神技之临时表的更多相关文章

  1. Redis 内存优化神技,小内存保存大数据

    大家好,我是「码哥」,大家可以叫我靓仔. 这次码哥跟大家分享一些优化神技,当你面试或者工作中你遇到如下问题,那就使出今天学到的绝招,一招定乾坤! 如何用更少的内存保存更多的数据? 我们应该从 Redi ...

  2. Java调用oracle存储过程通过游标返回临时表数据

    注:本文来源于 <  Java调用oracle存储过程通过游标返回临时表数据   > Java调用oracle存储过程通过游标返回临时表数据 项目开发过程中,不可避免的会用到存储过程返回结 ...

  3. ORACLE使用GV_$TEMP_SPACE_HEADER统计临时表空使用情况不准确的问题

    以前写了一篇ORACLE临时表空间总结的文章, 里面介绍了几个查看临时表空间使用情况的脚本,其中一个脚本如下所示: SELECT TU.TABLESPACE_NAME                  ...

  4. ORACLE中创建和删除临时表

    CREATE GLOBAL TEMPORARY TABLE TABLENAME (   COL1  VARCHAR2(10),   COL2  NUMBER) ON COMMIT PRESERVE(D ...

  5. Oracle 临时事务表 全局临时表_global temporary table

    所有的操作都在一个事务里,事务提交后,此表清空,特别适合做插入删除频率特别高的临时表操作,比如插入完数据就开始查询,查询完就删掉等,用完就扔! 临时表分事务级临时表和会话级临时表. 事务级临时表只对当 ...

  6. jdbctemplate 调用oracle 有返回(会话型临时表数据的)结果的存储过程

    注:本文为博主 原创. jdbctemplate 调用oracle存储过程 事务 临时表  有返回结果 1:java 代码 本逻辑代码本是想把 java 代码里的list<Strign>类 ...

  7. 【Oracle】恢复丢失的临时表空间文件

    Oracle 11g以后,临时表空间文件是可以在重启数据库以后自动生成的(当然也可以在相同目录再建一个临时表空间文件),模拟实验如下: 1)删除临时表空间数据文件 SYS@ENMOEDU> se ...

  8. Oracle 计划任务批量清理临时表实例

    昨天发现近一段时间,公司某oracle库数据泵方式备份比之前慢了很多,备份集大小并未增长太多.查看了下发现该用户下存在几十万张表. 一.问题分析 1.查看用户下面的表 select count(*) ...

  9. SQL 语句调优 where 条件 数据类型 临时表 索引

    基本原则 避免全表扫描 建立索引 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理 尽量避免大事务操作,提高系统并发能力 使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方 ...

  10. Oracle修改被占用的临时表结构

    这两天在修改临时表的类型时,提示”attempt to create,alter or drop an index on temporary table already in use“的错误,由于临时 ...

随机推荐

  1. Effective Python:第2条 遵循PEP 8风格指南

    PEP8文档:https://peps.python.org/pep-0008/ 与空白有关的建议: 用空格(space)表示缩进,而不要用制表符(tab). 和语法相关的每一层缩进都用4个空格表示. ...

  2. maven报错:501 HTTPS Required

    maven报错:501 HTTPS Required 简单来说,如果报错中出现http://repo1.maven.org/maven2/的字样的话,那么大概率就是Maven仓库的设置里的地址有问题, ...

  3. 力扣1077(MySQL)-项目员工Ⅲ(中等)

    题目: 写 一个 SQL 查询语句,报告在每一个项目中经验最丰富的雇员是谁.如果出现经验年数相同的情况,请报告所有具有最大经验年数的员工. 查询结果格式在以下示例中: employee_id 为 1 ...

  4. 「直播回顾」Mars应用与最佳实践

    简介: 本文首先对Mars的概念.功能.优势进行了介绍,随后,对Mars几个典型的应用场景进行介绍,并通过两个Demo展示了在使用Mars后数据科学性能的提升,最后总结了Mars的最佳实践,让使用Ma ...

  5. [FAQ] FastAdmin epay 微信公众号支付 JSAPI 支付必须传 openid ?

    使用 FastAdmin 的 epay 插件时,我们通过传不同的 method 决定支付方式. method=mp 时表示公众号支付,此时必须要 openid,但是插件里并没有说明如何获取. 其实这个 ...

  6. C# 二进制数组与结构体的互转

    本文将告诉大家在 dotnet 里面的二进制基础处理知识,如何在 C# 里面将结构体数组和二进制数组进行相互转换的简单方法 尽管本文属于基础入门的知识,但是在阅读之前还请自行了解 C# 里面的结构体内 ...

  7. SpringBoot项目添加2FA双因素身份认证

    什么是 2FA(双因素身份验证)? 双因素身份验证(2FA)是一种安全系统,要求用户提供两种不同的身份验证方式才能访问某个系统或服务.国内普遍做短信验证码这种的用的比较少,不过在国外的网站中使用双因素 ...

  8. 用Multisim验证简易测谎仪

    用Multisim验证简易测谎仪 测谎仪电路如下图所示: 节点1,2之间用10M欧的电位计代表人体表电阻,原理是撒谎出汗的话,体表电阻就小.Q1,Q2构成互补音频振荡器,振荡频率由R2.C1和R12共 ...

  9. LSP(Language Server Protocol)简介

    概述 Language Server Protocol(LSP)是微软2016年提出的一项通讯协议方案.该方案定义了一套协议,用于在IDE或编辑器和提供代码补全.转到定义等功能的Language Se ...

  10. vue+vant+js实现购物车原理小demo(基础版)

    电商毕业设计里的一个购物车demo,拿vue+vant需要写的核心计算代码只有12行.效果图: main.js: Vue.use(Stepper); .vue文件 <template> & ...