首页 > 数据库 >Oracle优化神技之临时表

Oracle优化神技之临时表

时间:2024-06-03 21:16:09浏览次数:20  
标签:临时 T1 Oracle JINGYU GTT TABLE 神技 table 优化

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:

标签:临时,T1,Oracle,JINGYU,GTT,TABLE,神技,table,优化
From: https://www.cnblogs.com/jyzhao/p/18229639/oracle-you-hua-shen-ji-zhi-lin-shi-biao

相关文章

  • Amazon Q Developer 实战:从新代码生成到遗留代码优化(下)
    简述本文是使用AmazonQDeveloper探索如何在VisualStudioCode集成编程环境(IDE),从新代码生成到遗留代码优化的续集。在上一篇博客《AmazonQDeveloper实战:从新代码生成到遗留代码优化(上)》中,我们演示了如何使用AmazonQDeveloper编写新代码和优化遗留代码。正如我们在上......
  • 记一次基于倒序索引的SQL优化
    本文测试环境为SQLserver2019背景某业务流水表,会基于固定范围内的业务编号做写入以及查询操作,热数据的量级在亿级别,一个典型的查询是基于业务编码查询最新(时间戳)某种状态的前N条数据简化后的表结构如下createtableTestTable01(idbigintidentit......
  • 通过精准的内容分发和优化的路由策略,确保企业客户能够以高速稳定的方式接入互联网,访问
    为了满足企业对于高质量、高效率互联网接入的需求,中国联通国际推出了ChinaDIA及GlobalDIA产品,旨在为企业客户提供专属IP地址和独享带宽,保证企业客户能够以更加稳定、高速的方式访问全球互联网内容。产品优势带宽独享:中国联通国际拥有丰富的全球网络资源,凭借行业领先的技术和......
  • Python信贷风控模型:梯度提升Adaboost,XGBoost,SGD, GBOOST, SVC,随机森林, KNN预测金
    原文链接:http://tecdat.cn/?p=26184 原文出处:拓端数据部落公众号最近我们被客户要求撰写关于信贷风控模型的研究报告,包括一些图形和统计输出。在此数据集中,我们必须预测信贷的违约支付,并找出哪些变量是违约支付的最强预测因子?以及不同人口统计学变量的类别,拖欠还款的概率如何......
  • 如何利用AI客服销售系统优化企业的内部管理?
    龙兵科技,自主研发,专注软件研发10年,欢迎主页咨询。在当今的商业环境中,企业的内部管理问题已经成为了一个不容忽视的问题。如何有效地解决这些问题,提高企业的运营效率和客户满意度,是每一个企业都需要面对的挑战。近年来,随着人工智能技术的发展,一种名为《AI销售系统》的工具正在......
  • 【机器学习】——驱动智能制造的青春力量,优化生产、预见故障、提升质量
    目录一.优化生产流程1.1数据收集1.2数据预处理1.3模型训练1.4优化建议1.5示例代码二.预测设备故障2.1数据收集2.2数据预处理2.3模型训练2.4故障预测2.5示例代码三.提升产品质量3.1数据收集3.2数据预处理3.3模型训练3.4质量提升3.5示例代码......
  • Oracle获取吞吐量和IOPS的脚本
     Oracle获取吞吐量和IOPS的脚本 数据底层存储要换盘,对新盘做IOPS压测。并花了点时间写了脚本获取数据库每秒的吞吐量和IOPS信息。可以将数据导成excel并绘制为折线图等统计图。  --获取IOPS(当前实例)selectto_char(t.begin_interval_time,'yyyy-mm-ddhh24:mi')......
  • 图神经网络(GNN)在生产过程优化中的应用介绍
    目录一、说明二、图神经网络和应用2.1什么是图神经网络?2.2将生产系统建模为图形2.3过程模拟和假设分析2.4优化生产计划三、生产系统中的图形数据表示3.1生产图中的节点表示3.2生产图中的边缘表示3.3图形表示的好处3.4将GNN与图形表示集成3.5实际应......
  • Oracle RU和RUR(补丁)
    以前Oracle的周期是约5年省级一个大版本,在这个大版本上做小的升级(PSU与BP),在12c发布以后,oracle数据库产品的新版本发布改为每年一次。随着版本的变化,oracle的升级也发生了变化。12.2以后,主要是通过RU(ReleaseUpdates)与RUR(ReleaseUpdateRevisions)升级,那么什么是RU(ReleaseUpd......
  • 基于粒子群算法优化Kmeans聚类的居民用电行为分析研究(Matlb代码实现)
     ......