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. 一个简单docker服务镜像的制作,手把手教你制作一个flask的docker容器服务镜像。

    OK,docker的安装就不多说了.(自己去搜吧) 下面开始讲如何制作镜像: 1.pull拉取一个centos镜像,随意拉取,可以是ubuntu sudo docker pull centos:7 2 ...

  2. Django框架——Q查询进阶、ORM查询优化、事务操作、字段类型、字段参数、Ajax、Content—Type、ajax携带文件

    Q查询进阶 from django.db.models import Q q_obj = Q() # 1.产生q对象 q_obj.connector = 'or' # 默认多个条件的连接是and可以修 ...

  3. b站的视频进度条悬浮预览视频画面实现方式

    1.探究 在看b站视频,滑到进度条的时候突发奇想,想知道这个预览图是怎么做到的 打开控制台,发现每次移动鼠标悬浮位置的时候都会发出一条网络请求,并且该请求的size显示来源于内存,当时以为每次加载视频 ...

  4. 【笔记】报错:numeric or value error: character to number conversion error

    报错:numeric or value error: character to number conversion error 报错如下: 数据库操作错误."2327,13619/v1:65 ...

  5. 牛客网-SQL专项训练14

    ①通过子查询的方式从衬衫表SHIRTABLE中选取出销售单价shirt_price高于全部衬衫的平均价格的衬衫名字:B 解析: 题目要求需要用到子查询,故排除AC选项,而D选项在where子句中使用了 ...

  6. 力扣224(java)-基本计算器(困难)

    题目: 给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值. 注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() . 示例 1: 输入:s = " ...

  7. PolarDB-X 2.0:使用一个透明的分布式数据库是一种什么体验

    简介: 透明分布式,是PolarDB-X即将发布的能力,它能让应用在使用PolarDB-X的过程中,犹如使用单机数据库一般的体验.与传统的中间件类型的"分布式数据库"相比,有了透明 ...

  8. sysAK(青囊)系统运维工具集:如何实现高效自动化运维?| 龙蜥技术

    ​简介:What is sysAK.典型工具介绍.开源 3 方面介绍了 sysAK 系统,目前 sysAK 工具集已经在龙蜥社区开源,并且在系统运维 SIG.跟踪诊断 SIG 一起共建,希望大家后期加 ...

  9. VisualStudio 使用 FastTunnel 辅助搭建远程调试环境

    有时候需要远程调试一些用户问题,期望能使用本机的 Visual Studio 开发环境,调试远程的用户的设备上的应用.这时会遇到的一个问题是如何让本机的 Visual Studio 可以连接上远程的用 ...

  10. WPF dotnet core 的 Blend SDK Behaviors 库

    之前版本是通过安装 Blend SDK 支持 Behaviors 库的,但是这个方法都是通过引用 dll 的方式,不够优雅.在升级到 dotnet core 3.0 的时候就需要使用 WPF 官方团队 ...