爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      Oracle全局临时表

      首页 知识中心 数据库 文章详情页

      Oracle全局临时表

      2023-05-31 08:46:08 阅读次数:118

      Oracle

      Oracle全局临时表

      目前所有使用Oracle作为数据库支撑平台的应用,大部分是数据量比较庞大的系统,即表的数据量级一般情况下都是在百万级以上。当然,在Oracle中创建分区是一种不错的选择,但是当发现应用有多张表关联的时候,并且这些表大部分都比较庞大,而关联的时候发现其中的某一张或者某几张表关联之后得到的结果集非常小,并且查询得到这个结果集的速度非常快,那么这个时候考虑在Oracle中创建“临时表”。

      在创建数据表的时候,如果没有特殊地指明,那么创建的表是一个永久的关系型表,也就是说,这个表中对应的数据,除非是显式地删除,否则表中的数据是永远都存在的。相对应的,在Oracle数据库中,还有一种类型的表,叫做临时表。这个临时表跟永久表最大的区别就是表中的数据不会永远地存在。当一个会话结束或者事务结束的时候,这个临时表中的数据,不用用户自己删除,数据库自己会自动清除。

      Oracle的临时表创建之后基本不占用表空间,如果没有指定临时表(包括临时表的索引)存放的表空间,那么插入到临时表的数据是存放在Oracle系统的默认临时表空间中(TEMP),一个系统可能有多个临时表空间。临时表的数据只能存放在临时表空间中。

      临时表的数据只是在事务期间存在,对于会话类型的临时表,数据在会话期间存在,会话的数据对于当前会话私有,每个会话只能看到并修改自己的数据。DML锁不会加到临时表的数据上。可以对临时表创建索引、视图、触发器,可以用exp和imp工具导入导出表的定义,但是不能导出数据。

      (一)临时表的特点

      l 多用户操作的独立性:对于使用同一张临时表的不同用户,Oracle都会分配一个独立的TEMP SEGMENT,这样就避免了多个用户在对同一张临时表操作时发生交叉,从而保证了多个用户操作的并发性和独立性。

      l 数据的临时性:既然是临时表,顾名思义,存放在该表中的数据是临时性的。Oracle根据创建临时表时指定的参数(ON COMMIT DELETE ROWS /ON COMMIT PRESERVE ROWS),自动将数据TRUNCATE掉。

      (二)临时表的分类

      Oracle数据库根据临时表的性质不同,可以分为事务临时表(ON COMMIT DELETE ROWS)与会话临时表(ON COMMIT PRESERVE ROWS)。

      1、事务临时表

      事务临时表是指数据只有在当前事务内有效,该临时表与事务相关,当进行事务提交或者事务回滚的时候,临时表中的数据将自动被清空,其它的内容和会话级的临时表的一致(包括退出SESSION的时候,事务级的临时表的数据也会被清空)。一般情况下,如果在创建数据表的时候,没有特殊指明表是会话临时表的话,那么该表默认为事务临时表。

      以下三种情况下,事务临时表中的数据就会被清空:

      ① 提交事务(COMMIT)

      ② 回滚事务(ROLLBACK)

      ③ 退出SESSION

      创建事务临时表的语法如下所示:

      CREATE GLOBAL TEMPORARY TABLE  TABLE_NAME

      (COL1 TYPE1,COL2 TYPE2...)

      [ON COMMIT DELETE ROWS];

      事务临时表示例如下所示:

      SYS@lhrdb> CREATE GLOBAL TEMPORARY TABLE CGTT_DELETE_LHR AS SELECT * FROM SCOTT.EMP WHERE 1=2;

      Table created.

      SYS@lhrdb> INSERT INTO CGTT_DELETE_LHR SELECT * FROM SCOTT.EMP WHERE ROWNUM<=5;

      5 rows created.

      SYS@lhrdb> SELECT * FROM CGTT_DELETE_LHR;

           EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

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

            7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20

            7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

            7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

            7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20

            7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

      SYS@lhrdb> COMMIT;

      Commit complete.

      SYS@lhrdb>  SELECT * FROM CGTT_DELETE_LHR;

      no rows selected

      从示例中可以看到,当执行完COMMIT后,当前会话就看不到数据了。

      2、会话临时表

      会话临时表,顾名思义,是指数据只在当前会话内是有效的临时表。关闭当前会话或者进行新的连接之后,数据表中的内容就会被清除。

      CREATE GLOBAL TEMPORARY TABLE  TABLE_NAME

      (COL1 TYPE1,COL2 TYPE2...)

      ON COMMIT PRESERVE ROWS;

      会话临时表示例如下所示:

      SYS@lhrdb> CREATE GLOBAL TEMPORARY TABLE CGTT_PRESERVE_LHR ON COMMIT PRESERVE ROWS AS SELECT * FROM SCOTT.EMP WHERE 1=2;

      Table created.

      SYS@lhrdb> INSERT INTO CGTT_PRESERVE_LHR SELECT * FROM SCOTT.EMP WHERE ROWNUM<=5;

      5 rows created.

      SYS@lhrdb> SELECT * FROM CGTT_PRESERVE_LHR;

           EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

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

            7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20

            7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

            7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

            7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20

            7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

      SYS@lhrdb> COMMIT;

      Commit complete.

      SYS@lhrdb> SELECT * FROM CGTT_PRESERVE_LHR;

           EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

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

            7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20

            7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

            7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

            7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20

            7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

      SYS@lhrdb> CONN / AS SYSDBA

      Connected.

      SYS@lhrdb> SELECT * FROM CGTT_PRESERVE_LHR;

      no rows selected

      从示例中可以看到,当执行完COMMIT后,数据依然存在,但是当重新连接会话后,数据就被清空了。

      查看一张表是否临时表,可以从DBA_TABLES视图的DURATION列来查询:

      SELECT UT.TABLE_NAME,

             UT.TABLESPACE_NAME,

             UT.TEMPORARY,

             DECODE(UT.DURATION,'SYS$SESSION','会话级','SYS$TRANSACTION','事务级') 临时表类型

        FROM DBA_TABLES UT

       WHERE UT.TEMPORARY = 'Y'

         AND UT.TABLE_NAME LIKE '%CGTT%';

       

      TABLE_NAME                     TABLESPACE_NAME                T TYPE

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

      CGTT_DELETE_LHR                                               Y 事务级

      CGTT_PRESERVE_LHR                                             Y 会话级

       

      会话临时表与事务临时表主要的差异就在于删除数据的时机不同。事务临时表是在事务提交或回滚的时候清除数据,而会话临时表则是在关闭当前会话的时候清除数据。只要当前会话没有关闭,即使事务完成了,会话临时表中的数据仍然存在,不会被清除。

      (三)临时表的统计信息

       

      临时表默认是不收集统计信息的,但是可以使用DBMS_STATS.GATHER_SCHEMA_STATS在SCHEMA级别收集,需要设置GATHER_TEMP为TRUE(默认为FALSE);也可以和普通表一样使用GATHER_TABLE_STATS在表级别来收集。需要注意的是,只能收集会话临时表的统计信息,不能收集事务临时表的统计信息。会话临时表的统计信息是被所有的会话所共享的,所以,在一般情况下,不建议收集临时表的统计信息,否则可能会导致很严重的数据库性能问题。临时表的统计信息在生成执行计划时一般是被动态采样的。

       

      下面给出一个示例,该示例演示了由于收集了临时表的统计信息引发的性能问题。

      环境准备:

      DROP TABLE T_20170619_LHR CASCADE CONSTRAINTS PURGE;

      DROP TABLE T_CGTT_20170619_LHR CASCADE CONSTRAINTS PURGE;

       

      CREATE TABLE T_20170619_LHR (

        ID NUMBER NOT NULL,

        N NUMBER,

        CONTENTS VARCHAR2(4000)

      );

       

      CREATE GLOBAL TEMPORARY TABLE T_CGTT_20170619_LHR (

       ID NUMBER NOT NULL,

       T_ID NUMBER NOT NULL,

       N NUMBER,

       CONTENTS VARCHAR2(4000)

      ) ON COMMIT PRESERVE ROWS

      ;

       

      EXECUTE DBMS_RANDOM.SEED(0);

      INSERT INTO T_20170619_LHR

      SELECT  ROWNUM,  ROWNUM, DBMS_RANDOM.STRING('A', 50)

      FROM DUAL

      CONNECT BY LEVEL <= 10

      ORDER BY DBMS_RANDOM.RANDOM;

       

      INSERT INTO T_CGTT_20170619_LHR

      SELECT ROWNUM, ROWNUM, ROWNUM, DBMS_RANDOM.STRING('B', 50)

      FROM DUAL CONNECT BY LEVEL <= 100000

      ORDER BY DBMS_RANDOM.RANDOM;

      COMMIT;

       

      SELECT COUNT(*) FROM T_20170619_LHR; --10

      SELECT COUNT(*) FROM T_CGTT_20170619_LHR; --100000

      EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'LHR',TABNAME => 'T_20170619_LHR',ESTIMATE_PERCENT => 100,CASCADE=>TRUE);

      正常的执行计划如下:

      SET LINESIZE 1000

      ALTER SESSION SET STATISTICS_LEVEL=ALL ;

      SELECT *

      FROM T_20170619_LHR A,T_CGTT_20170619_LHR B

      WHERE A.ID = B.T_ID;

      SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST ADVANCED'));

       

      PLAN_TABLE_OUTPUT

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

      SQL_ID  awa3ys5000qc1, child number 0

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

      SELECT * FROM T_20170619_LHR A,T_CGTT_20170619_LHR B WHERE A.ID = B.T_ID

       

      Plan hash value: 1110746760

       

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

      | Id  | Operation          | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |

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

      |   0 | SELECT STATEMENT   |                     |      1 |        |       |   272 (100)|          |     10 |00:00:00.03 |     990 |       |       |          |

      |*  1 |  HASH JOIN         |                     |      1 |     10 | 20980 |   272   (1)| 00:00:04 |     10 |00:00:00.03 |     990 |   821K|   821K| 1142K (0)|

      |   2 |   TABLE ACCESS FULL| T_20170619_LHR      |      1 |     10 |   570 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |       |       |          |

      |   3 |   TABLE ACCESS FULL| T_CGTT_20170619_LHR |      1 |  90611 |   176M|   268   (1)| 00:00:04 |    100K|00:00:00.01 |     984 |       |       |          |

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

      Query Block Name / Object Alias (identified by operation id):

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

       

         1 - SEL$1

         2 - SEL$1 / A@SEL$1

         3 - SEL$1 / B@SEL$1

       

      Outline Data

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

       

        /*+

            BEGIN_OUTLINE_DATA

            IGNORE_OPTIM_EMBEDDED_HINTS

            OPTIMIZER_FEATURES_ENABLE('11.2.0.3')

            DB_VERSION('11.2.0.3')

            ALL_ROWS

            OUTLINE_LEAF(@"SEL$1")

            FULL(@"SEL$1" "A"@"SEL$1")

            FULL(@"SEL$1" "B"@"SEL$1")

            LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1")

            USE_HASH(@"SEL$1" "B"@"SEL$1")

            END_OUTLINE_DATA

        */

       

      Predicate Information (identified by operation id):

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

       

         1 - access("A"."ID"="B"."T_ID")

       

      Column Projection Information (identified by operation id):

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

       

         1 - (#keys=1) "A"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000], "A"."N"[NUMBER,22], "B"."ID"[NUMBER,22],

             "B"."CONTENTS"[VARCHAR2,4000], "B"."N"[NUMBER,22]

         2 - "A"."ID"[NUMBER,22], "A"."N"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000]

         3 - "B"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "B"."N"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000]

       

      Note

      -----

         - dynamic sampling used for this statement (level=2)

      这个时候执行计划是正确的,因为T_20170619_LHR是小表(共10行数据),而T_CGTT_20170619_LHR是大表(共100000行数据),处于被驱动的位置,是正确的,而且在执行中,Oracle对大表使用了动态采样。下面新开一个会话,然后收集全局临时表T_CGTT_20170619_LHR表的统计信息,如下:

      SYS@orclasm > SELECT TABLE_NAME,

        2         PARTITION_NAME,

        3         LAST_ANALYZED,

        4         PARTITION_POSITION,

        5         NUM_ROWS

        6    FROM DBA_TAB_STATISTICS T

        7   WHERE TABLE_NAME = 'T_CGTT_20170619_LHR';

       

      TABLE_NAME                     PARTITION_NAME                 LAST_ANALYZED       PARTITION_POSITION   NUM_ROWS

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

      T_CGTT_20170619_LHR

       

      SYS@orclasm > EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'LHR',TABNAME => 'T_CGTT_20170619_LHR',ESTIMATE_PERCENT => 100,CASCADE=>TRUE,NO_INVALIDATE => FALSE);  --注意这里要加NO_INVALIDATE => FALSE

       

      PL/SQL procedure successfully completed.

       

      SYS@orclasm > SELECT TABLE_NAME,

        2         PARTITION_NAME,

        3         LAST_ANALYZED,

        4         PARTITION_POSITION,

        5         NUM_ROWS

        6    FROM DBA_TAB_STATISTICS T

        7   WHERE TABLE_NAME = 'T_CGTT_20170619_LHR';

       

      TABLE_NAME                     PARTITION_NAME                 LAST_ANALYZED       PARTITION_POSITION   NUM_ROWS

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

      T_CGTT_20170619_LHR                                           2017-06-19 15:30:24                             0

      然后回到刚才的会话,继续查询执行计划,发现执行计划变动了:

      SET LINESIZE 1000

      ALTER SESSION SET STATISTICS_LEVEL=ALL ;

      SELECT *

      FROM T_20170619_LHR A,T_CGTT_20170619_LHR B

      WHERE A.ID = B.T_ID;

      SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST ADVANCED'));

       

      PLAN_TABLE_OUTPUT

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

      SQL_ID  awa3ys5000qc1, child number 0

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

      SELECT * FROM T_20170619_LHR A,T_CGTT_20170619_LHR B WHERE A.ID = B.T_ID

       

      Plan hash value: 991471220

       

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

      | Id  | Operation          | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |

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

      |   0 | SELECT STATEMENT   |                     |      1 |        |       |     6 (100)|          |     10 |00:00:00.05 |     989 |       |       |          |

      |*  1 |  HASH JOIN         |                     |      1 |      1 |  2098 |     6  (17)| 00:00:01 |     10 |00:00:00.05 |     989 |    10M|  2143K|   11M (0)|

      |   2 |   TABLE ACCESS FULL| T_CGTT_20170619_LHR |      1 |      1 |  2041 |     2   (0)| 00:00:01 |    100K|00:00:00.01 |     982 |       |       |          |

      |   3 |   TABLE ACCESS FULL| T_20170619_LHR      |      1 |     10 |   570 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       7 |       |       |          |

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

      Query Block Name / Object Alias (identified by operation id):

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

       

         1 - SEL$1

         2 - SEL$1 / B@SEL$1

         3 - SEL$1 / A@SEL$1

       

      Outline Data

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

       

        /*+

            BEGIN_OUTLINE_DATA

            IGNORE_OPTIM_EMBEDDED_HINTS

            OPTIMIZER_FEATURES_ENABLE('11.2.0.3')

            DB_VERSION('11.2.0.3')

            ALL_ROWS

            OUTLINE_LEAF(@"SEL$1")

            FULL(@"SEL$1" "B"@"SEL$1")

            FULL(@"SEL$1" "A"@"SEL$1")

            LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")

            USE_HASH(@"SEL$1" "A"@"SEL$1")

            END_OUTLINE_DATA

        */

       

      Predicate Information (identified by operation id):

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

       

         1 - access("A"."ID"="B"."T_ID")

       

      Column Projection Information (identified by operation id):

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

       

         1 - (#keys=1) "B"."T_ID"[NUMBER,22], "A"."ID"[NUMBER,22], "B"."ID"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000], "B"."N"[NUMBER,22],

             "A"."CONTENTS"[VARCHAR2,4000], "A"."N"[NUMBER,22]

         2 - "B"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "B"."N"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000]

         3 - "A"."ID"[NUMBER,22], "A"."N"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000]

      可见,没有使用动态采样,而且生成的执行计划是错误的,因为大表(10W条记录)竟然做了驱动表。当删除临时表的统计信息后,执行计划恢复正常:

      LHR@orclasm > EXEC DBMS_STATS.DELETE_TABLE_STATS(OWNNAME => 'LHR',TABNAME => 'T_CGTT_20170619_LHR',NO_INVALIDATE => FALSE);

       

      PL/SQL procedure successfully completed.

       

      SET LINESIZE 1000

      ALTER SESSION SET STATISTICS_LEVEL=ALL ;

      SELECT *

      FROM T_20170619_LHR A,T_CGTT_20170619_LHR B

      WHERE A.ID = B.T_ID;

      SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST ADVANCED'));

       

      PLAN_TABLE_OUTPUT

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

      SQL_ID  awa3ys5000qc1, child number 0

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

      SELECT * FROM T_20170619_LHR A,T_CGTT_20170619_LHR B WHERE A.ID = B.T_ID

       

      Plan hash value: 1110746760

       

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

      | Id  | Operation          | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |

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

      |   0 | SELECT STATEMENT   |                     |      1 |        |       |   272 (100)|          |     10 |00:00:00.03 |     990 |       |       |          |

      |*  1 |  HASH JOIN         |                     |      1 |     10 | 20980 |   272   (1)| 00:00:04 |     10 |00:00:00.03 |     990 |   821K|   821K| 1142K (0)|

      |   2 |   TABLE ACCESS FULL| T_20170619_LHR      |      1 |     10 |   570 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |       |       |          |

      |   3 |   TABLE ACCESS FULL| T_CGTT_20170619_LHR |      1 |  90611 |   176M|   268   (1)| 00:00:04 |    100K|00:00:00.01 |     984 |       |       |          |

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

      Query Block Name / Object Alias (identified by operation id):

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

       

         1 - SEL$1

         2 - SEL$1 / A@SEL$1

         3 - SEL$1 / B@SEL$1

       

      Outline Data

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

       

        /*+

            BEGIN_OUTLINE_DATA

            IGNORE_OPTIM_EMBEDDED_HINTS

            OPTIMIZER_FEATURES_ENABLE('11.2.0.3')

            DB_VERSION('11.2.0.3')

            ALL_ROWS

            OUTLINE_LEAF(@"SEL$1")

            FULL(@"SEL$1" "A"@"SEL$1")

            FULL(@"SEL$1" "B"@"SEL$1")

            LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1")

            USE_HASH(@"SEL$1" "B"@"SEL$1")

            END_OUTLINE_DATA

        */

       

      Predicate Information (identified by operation id):

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

       

         1 - access("A"."ID"="B"."T_ID")

       

      Column Projection Information (identified by operation id):

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

       

         1 - (#keys=1) "A"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000], "A"."N"[NUMBER,22], "B"."ID"[NUMBER,22],

             "B"."CONTENTS"[VARCHAR2,4000], "B"."N"[NUMBER,22]

         2 - "A"."ID"[NUMBER,22], "A"."N"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000]

         3 - "B"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "B"."N"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000]

       

      Note

      -----

         - dynamic sampling used for this statement (level=2)

       

      所以,对于临时表尽量使用动态采样,而不应该收集它的统计信息。因为统计信息被所有会话所共享,而全局临时表的数据是与会话相关的,不同的会话其含有的数据量是不同的。

       

      真题1、 You issued the following command:

      CREATE GLOBAL TEMPORARY TABLE admin_work_area

      (startdate DATE,

      enddate DATE,

      class CHAR(20))

      ON COMMIT DELETE ROWS

      TABLESPACE tbs_t1;

      An index is then created on the ADMIN_WORK_AREA temporary table.  Which two statements are true regarding the TBS_T1 tablespace in the above command? (Choose two.)

      A、It stores only the temporary table but not its indexes.

      B、It stores both the temporary table as well as its indexes.

      C、It must be a nondefault temporary tablespace for the database.

      D、It can be a default or nondefault temporary tablespace for the database.

      E、It must be the default temporary tablespace of the user who issues the command.

      答案:B、D。

      本题中的命令是在TBS_T1表空间中创建了一个事务临时表ADMIN_WORK_AREA,并且在该临时表上创建了一个索引,最后要求选出有关TBS_T1表空间的2个正确的选项。

      本题中,对于选项A,TBS_T1表空间只存数据而不存索引,说法错误,应该都存储。所以,选项A错误。

      对于选项B,TBS_T1表空间即存储数据也存储索引,说法正确。所以,选项B正确。

      对于选项C,TBS_T1表空间必须是非默认的表空间,说法错误,默认和非默认都可以。所以,选项C错误。

      对于选项D,TBS_T1表空间可以是一个默认或非默认的数据库的临时表空间。所以,选项D正确。

      对于选项E,TBS_T1表空间必须是默认的表空间,说法错误,默认和非默认都可以。所以,选项E错误。

      所以,本题的答案为B、D。








       

          临时表(Tempotary table)用于保存事务或会话期间的中间结果集。临时表中保存的数据只对当前会话可见,所有会话都看不到其他会话的数据;即使当前会话已经提交了(commit)数据,别的会话也看不到它的数据。对于临时表,不存在多用户并发的问题,因为一个会话不会因为使用一个临时表而阻塞另一个会话。即使我们“锁住”了临时表,也不会妨碍其他会话使用临时表。

           

          临时表比常规表生成的redo少得多。不过由于临时表必须为其中包含的数据生成undo信息,所以也会生成一定的redo。update和delete会生成最多的undo,insert和select生成的undo最少。

       

          临时表会从当前登录用户的临时表空间分配存储空间,或者如果从一个定义者权限过程访问临时表,就会使用该过程所有者的临时表空间。全局临时表实际上是表本身的一个模板。创建临时表的动作不涉及存储空间分配,不会为此初始区段,这与常规表有所不同。对于临时表,运行时当一个会话第一次在临时表中放入数据时,才会为该会话创建一个临时段。由于每个回话会得到其自己的临时段(而不是一个现有段的一个区段),每个用户可能在不同的表空间为其看in是表分配空间。USER1的临时表空间可能设置为TEMP1,因此他的临时表会从这个表空间分配。USER2可能把TEMP2作为其临时表空间,它的临时表就会从那里分配。

       

         Oracle的临时表与其他关系数据库中的临时表类似,主要区别是:Oracle的临时表是“静态”定义的。每个数据库只创建一次临时表,而不是为数据库中的每个存储过程都创建一次。在Oracle历史表一定存在,他们作为对象放在数据字典中,但是在会话向临时表中放入数据之前,临时表看上去总是空的。由于临时表是静态定义的,所以你能创建引用临时表的视图,还可以创建存储过程只用静态SQL来引用临时表,等等。

       

          临时表可以是会话的(临时表中的数据可以跨提交存在,即提交之前仍然存在,但是断开连接后再连接时数据就没有了),也可以是基于事务的(提交之后数据就消失)。语法如下:

      • 基于会话  create global temporary table temp_table_session (...)  on commit preserve rows

               基于会话的临时表,在会话断开之前,或者通过一个delete或truncate物理地删除行之前,这些行会一直存在于这个临时表中。只有我的会话能看到这些行,即使我已经提交,其他会话也无法看到我的行。

      • 基于事务   create global temporary table temp_table_session (...)  on commit delete rows

                基于事务的临时表,我的会话提交时,临时表中的行就不见了。只需把分配给这个表的临时区段交回,这些行就会消失,在临时表的自动清除过程中不存在开销。

       

         

             临时表可以有永久表的许多属性。他们可以有触发器,检查约束,索引等。但永久表的某些特性在临时表中并不支持,这包括以下特性。

      • 不能有引用完整性约束。临时表不能作为外键的目标,也不能在临时表中定义外键。
      • 不能是IOT
      • 不能在任何类型的聚簇中
      • 不能分区
      • 不能通过ANALYZE表命令生成统计信息

              在所有数据库中,临时表的缺点之一就是优化器不能正常地得到临时表的真实统计信息。使用基于代价的优化器(CBO)时,有效的统计对于优化器的成败至关重要。


      全局临时表的统计信息是不能被收集的,如果被收集,它的统计信息肯定为0,会造成执行计划不准,所以要锁定它的统计信息,禁止系统自动收集。



      Oracle临时表使用注意事项      
       
       

       此文将给出在使用Oracle临时表的过程中需要注意的事项,并对这些特点进行验证。
         ① 临时表不支持物化视图
         ② 可以在临时表上创建索引
         ③ 可以基于临时表创建视图
         ④ 临时表结构可被导出,但内容不可以被导出
         ⑤ 临时表通常是创建在用户的临时表空间中的,不同用户可以有自己的独立的临时表空间
         ⑥ 不同的session不可以互相访问对方的临时表数据
         ⑦ 临时表数据将不会上DML(Data Manipulation Language)锁


      1. 临时表不支持物化视图
      1)环境准备
      (1)创建基于会话的临时表
      sec@ora10g> create global temporary table t_temp_session (x int) on commit preserve rows;

      Table created.

      sec@ora10g> col TABLE_NAME for a30
      sec@ora10g> col TEMPORARY for a10
      sec@ora10g> select TABLE_NAME,TEMPORARY from user_tables where table_name = 'T_TEMP_SESSION';

      TABLE_NAME                     TEMPORARY
      ------------------------------ ----------
      T_TEMP_SESSION                 Y

      (2)初始化两条数据
      sec@ora10g> insert into t_temp_session values (1);

      1 row created.

      sec@ora10g> insert into t_temp_session values (2);

      1 row created.

      sec@ora10g> commit;

      Commit complete.

      sec@ora10g> select * from t_temp_session;

               X
      ----------
               1
               2

      (3)在临时表 T_TEMP_SESSION 上添加主键
      sec@ora10g> alter table T_TEMP_SESSION add constraint PK_T_TEMP_SESSION primary key(x);

      Table altered.

      2)在临时表T_TEMP_SESSION上创建物化视图
      (1)创建物化视图日志日志
      sec@ora10g> create materialized view log on T_TEMP_SESSION with sequence, rowid (x) including new values;
      create materialized view log on T_TEMP_SESSION with sequence, rowid (x) including new values
      *
      ERROR at line 1:
      ORA-14451: unsupported feature with temporary table

      可见,在创建物化视图时便提示,临时表上无法创建物化视图日志。

      (2)创建物化视图
      sec@ora10g> create materialized view mv_T_TEMP_SESSION build immediate refresh fast on commit enable query rewrite as select * from T_TEMP_SESSION;
      create materialized view mv_T_TEMP_SESSION build immediate refresh fast on commit enable query rewrite as select * from T_TEMP_SESSION
                                                                                                                              *
      ERROR at line 1:
      ORA-23413: table "SEC"."T_TEMP_SESSION" does not have a materialized view log

      由于物化视图日志没有创建成功,因此显然物化视图亦无法创建。

      2.在临时表上创建索引
      sec@ora10g> create index i_t_temp_session on t_temp_session (x);

      Index created.

      临时表上索引创建成功。

      3.基于临时表创建视图
      sec@ora10g> create view v_t_temp_session as select * from t_temp_session where x<100;

      View created.

      基于临时表的视图创建成功。

      4.临时表结构可被导出,但内容不可以被导出
      1)使用exp工具备份临时表
      ora10g@secdb /home/oracle$ exp sec/sec file=t_temp_session.dmp log=t_temp_session.log tables=t_temp_session

      Export: Release 10.2.0.1.0 - Production on Wed Jun 29 22:06:43 2011

      Copyright (c) 1982, 2005, Oracle.  All rights reserved.


      Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
      With the Partitioning, OLAP and Data Mining options
      Export done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set

      About to export specified tables via Conventional Path ...
      . . exporting table                 T_TEMP_SESSION
      Export terminated successfully without warnings.

      可见在备份过程中,没有显示有数据被导出。

      2)使用imp工具的show选项查看备份介质中的SQL内容
      ora10g@secdb /home/oracle$ imp sec/sec file=t_temp_session.dmp full=y show=y

      Import: Release 10.2.0.1.0 - Production on Wed Jun 29 22:06:57 2011

      Copyright (c) 1982, 2005, Oracle.  All rights reserved.


      Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
      With the Partitioning, OLAP and Data Mining options

      Export file created by EXPORT:V10.02.01 via conventional path
      import done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set
      . importing SEC's objects into SEC
      . importing SEC's objects into SEC
       "CREATE GLOBAL TEMPORARY TABLE "T_TEMP_SESSION" ("X" NUMBER(*,0)) ON COMMIT "
       "PRESERVE ROWS "
       "CREATE INDEX "I_T_TEMP_SESSION" ON "T_TEMP_SESSION" ("X" ) "
      Import terminated successfully without warnings.

      这里体现了创建临时表和索引的语句,因此临时表的结构数据是可以被导出的。

      3)尝试导入数据
      ora10g@secdb /home/oracle$ imp sec/sec file=t_temp_session.dmp full=y ignore=y

      Import: Release 10.2.0.1.0 - Production on Wed Jun 29 22:07:16 2011

      Copyright (c) 1982, 2005, Oracle.  All rights reserved.


      Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
      With the Partitioning, OLAP and Data Mining options

      Export file created by EXPORT:V10.02.01 via conventional path
      import done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set
      . importing SEC's objects into SEC
      . importing SEC's objects into SEC
      Import terminated successfully without warnings.

      依然显示没有记录被导入。

      5.查看临时表空间的使用情况
      可以通过查询V$SORT_USAGE视图获得相关信息。
      sec@ora10g> select username,tablespace,session_num sid,sqladdr,sqlhash,segtype,extents,blocks from v$sort_usage;

      USERNAME TABLESPACE     SID SQLADDR     SQLHASH SEGTYPE EXTENTS  BLOCKS
      -------- ---------- ------- -------- ---------- ------- ------- -------
      SEC      TEMP           370 389AEC58 1029988163 DATA          1     128
      SEC      TEMP           370 389AEC58 1029988163 INDEX         1     128

      可见SEC用户中创建的临时表以及其上的索引均存放在TEMP临时表空间中。
      在创建用户的时候,可以指定用户的默认临时表空间,这样不同用户在创建临时表的时候便可以使用各自的临时表空间,互不干扰。

      6.不同的session不可以互相访问对方的临时表数据
      1)在第一个session中查看临时表数据
      sec@ora10g> select * from t_temp_session;

               X
      ----------
               1
               2

      此数据为初始化环境时候插入的数据。

      2)在单独开启一个session,查看临时表数据。
      ora10g@secdb /home/oracle$ sqlplus sec/sec

      SQL*Plus: Release 10.2.0.1.0 - Production on Wed Jun 29 22:30:05 2011

      Copyright (c) 1982, 2005, Oracle.  All rights reserved.


      Connected to:
      Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
      With the Partitioning, OLAP and Data Mining options

      sec@ora10g> select * from t_temp_session;

      no rows selected

      说明不同的session拥有各自独立的临时表操作特点,不同的session之间是不能互相访问数据。

      7.临时表数据将不会上DML(Data Manipulation Language)锁
      1)在新session中查看SEC用户下锁信息
      sec@ora10g> col username for a8
      sec@ora10g> select
        2       b.username,
        3       a.sid,
        4       b.serial#,
        5       a.type "lock type",
        6       a.id1,
        7       a.id2,
        8       a.lmode
        9  from v$lock a, v$session b
       10  where a.sid=b.sid and b.username = 'SEC'
       11  order by username,a.sid,serial#,a.type;

      no rows selected

      不存在任何锁信息。

      2)向临时表中插入数据,查看锁信息
      (1)插入数据
      sec@ora10g> insert into t_temp_session values (1);

      1 row created.

      (2)查看锁信息
      sec@ora10g> select
        2       b.username,
        3       a.sid,
        4       b.serial#,
        5       a.type "lock type",
        6       a.id1,
        7       a.id2,
        8       a.lmode
        9  from v$lock a, v$session b
       10  where a.sid=b.sid and b.username = 'SEC'
       11  order by username,a.sid,serial#,a.type;

                                     lock                                lock
      USERNAME        SID    SERIAL# type           id1         id2      mode
      -------- ---------- ---------- ------ ----------- ----------- ---------
      SEC             142        425 TO           12125           1         3
      SEC             142        425 TX           65554         446         6

      此时出现TO和TX类型锁。

      (3)提交数据后再次查看锁信息
      sec@ora10g> commit;

      Commit complete.

      sec@ora10g> select
        2       b.username,
        3       a.sid,
        4       b.serial#,
        5       a.type "lock type",
        6       a.id1,
        7       a.id2,
        8       a.lmode
        9  from v$lock a, v$session b
       10  where a.sid=b.sid and b.username = 'SEC'
       11  order by username,a.sid,serial#,a.type;

                                     lock                                lock
      USERNAME        SID    SERIAL# type           id1         id2      mode
      -------- ---------- ---------- ------ ----------- ----------- ---------
      SEC             142        425 TO           12125           1         3

      事务所TX被释放。TO锁保留。

      3)测试更新数据场景下锁信息变化
      (1)更新临时表数据
      sec@ora10g> update t_temp_session set x=100;

      1 row updated.

      (2)锁信息如下
                                     lock                                lock
      USERNAME        SID    SERIAL# type           id1         id2      mode
      -------- ---------- ---------- ------ ----------- ----------- ---------
      SEC             142        425 TO           12125           1         3
      SEC             142        425 TX          524317         464         6

      (3)提交数据
      sec@ora10g> commit;

      Commit complete.

      (4)锁信息情况
                                     lock                                lock
      USERNAME        SID    SERIAL# type           id1         id2      mode
      -------- ---------- ---------- ------ ----------- ----------- ---------
      SEC             142        425 TO           12125           1         3

      4)测试删除数据场景下锁信息变化
      (1)删除临时表数据
      sec@ora10g> delete from t_temp_session;

      1 row deleted.

      (2)查看锁信息
                                     lock                                lock
      USERNAME        SID    SERIAL# type           id1         id2      mode
      -------- ---------- ---------- ------ ----------- ----------- ---------
      SEC             142        425 TO           12125           1         3
      SEC             142        425 TX          327713         462         6

      (3)提交数据
      sec@ora10g> commit;

      Commit complete.

      (4)锁信息情况
                                     lock                                lock
      USERNAME        SID    SERIAL# type           id1         id2      mode
      -------- ---------- ---------- ------ ----------- ----------- ---------
      SEC             142        425 TO           12125           1         3

      5)总结
      在临时表上的增删改等DML操作都会产生TO锁和TX事务所。TO锁会从插入数据开始一直存在。
      但整个过程中都不会产生DML的TM级别锁。

      8.小结
        本文就临时表使用过程中常见的问题和特点进行了介绍。临时表作为Oracle的数据库对象,如果能够在理解这些特性基础上加以利用将会极大地改善系统性能。

      Good luck.

      secooler
      11.06.29

      -- The End --

                           

       
       
       
       
       
       



      在Oracle8i或以上版本中,可以创建以下两种临时表: 

      1。会话特有的临时表

      CREATE GLOBAL TEMPORARY ( ) 
      ON COMMIT PRESERVE ROWS; 

      2。事务特有的临时表

      CREATE GLOBAL TEMPORARY ( ) 
      ON COMMIT DELETE ROWS; 
      CREATE GLOBAL TEMPORARY TABLE MyTempTable  

      所建的临时表虽然是存在的,但是你试一下insert 一条记录然后用别的连接登上去select,记录是空的,明白了吧,我把下面两句话再贴一下: 

      --ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截断表(删除全部行) 
      --ON COMMIT PRESERVE ROWS 说明临时表是会话指定,当中断会话时ORACLE将截断表。 

      冲突的问题更本不用考虑.

      临时表只是保存当前会话(session)用到的数据,数据只在事务或会话期间存在。

      通过CREATE GLOBAL TEMPORARY TABLE命令创建一个临时表,对于事务类型的临时表, 数据只是在事务期间存在,对于会话类型的临时表,数据在会话期间存在。

      会话的数据对于当前会话私有。每个会话只能看到并修改自己的数据。DML锁不会加到 临时表的数据上。下面的语句控制行的存在性。

      ● ON COMMIT DELETE ROWS 表名行只是在事务期间可见 
      ● ON COMMIT PRESERVE ROWS 表名行在整个会话期间可见

      可以对临时表创建索引,视图,出发器,可以用export和import工具导入导出表的 定义,但是不能导出数据。表的定义对所有的会话可见。

      Temporary Tables临时表 

      1简介 

      ORACLE数据库除了可以保存永久表外,还可以建立临时表temporary tables。这些临时表用来保存一个会话SESSION的数据, 

      或者保存在一个事务中需要的数据。当会话退出或者用户提交commit和回滚rollback事务的时候,临时表的数据自动清空, 
      但是临时表的结构以及元数据还存储在用户的数据字典中。 

      临时表只在oracle8i以及以上产品中支持。 

      2详细介绍 

      Oracle临时表分为 会话级临时表 和 事务级临时表。 

      会话级临时表是指临时表中的数据只在会话生命周期之中存在,当用户退出会话结束的时候,Oracle自动清除临时表中数据。 
      事务级临时表是指临时表中的数据只在事务生命周期中存在。当一个事务结束(commit or rollback),Oracle自动清除临时表中数据。 

      临时表中的数据只对当前Session有效,每个Session都有自己的临时数据,并且不能访问其它Session的临时表中的数据。因此, 

      临时表不需要DML锁.当一个会话结束(用户正常退出 用户不正常退出 ORACLE实例崩溃)或者一个事务结束的时候,Oracle对这个会话的 

      表执行 TRUNCATE 语句清空临时表数据.但不会清空其它会话临时表中的数据. 

      你可以索引临时表和在临时表基础上建立视图.同样,建立在临时表上的索引也是临时的,也是只对当前会话或者事务有效. 

      临时表可以拥有触发器. 

      3建立临时表 

      临时表的定义对所有会话SESSION都是可见的,但是表中的数据只对当前的会话或者事务有效. 

      建立方法: 

      1) ON COMMIT DELETE ROWS 定义了建立事务级临时表的方法.

      CREATE GLOBAL TEMPORARY TABLE admin_work_area 
      (startdate DATE, 
      enddate DATE, 
      class CHAR(20)) 
      ON COMMIT DELETE ROWS;

       

      EXAMPLE:

      SQL> CREATE GLOBAL TEMPORARY TABLE admin_work_area 
       (startdate DATE, 
      enddate DATE, 
      class CHAR(20)) 
      ON COMMIT DELETE ROWS; 
      SQL> create table permernate( a number); 
      SQL> insert into admin_work_area values(sysdate,sysdate, ‘temperary table ‘); 
      SQL> insert into permernate values(1); 
      SQL> commit; 
      SQL> select * from admin_work_area; 
      SQL> select * from permernate; 
      A 
      1

       

      2)ON COMMIT PRESERVE ROWS 定义了创建会话级临时表的方法.

      CREATE GLOBAL TEMPORARY TABLE admin_work_area 
      (startdate DATE, 
      enddate DATE, 
      class CHAR(20)) 
      ON COMMIT PRESERVE ROWS; 
      EXAMPLE:

       

      会话1:

      SQL> drop table admin_work_area; 
      SQL> CREATE GLOBAL TEMPORARY TABLE admin_work_area 
      2 (startdate DATE, 
      3 enddate DATE, 
      4 class CHAR(20)) 
      5 ON COMMIT PRESERVE ROWS; 
      SQL> insert into permernate values(2); 
      SQL> insert into admin_work_area values(sysdate,sysdate, ‘session temperary ‘); 
      SQL> commit; 
      SQL> select * from permernate;
      
      A 
      ---------- 
      1 
      2
      
      SQL> select * from admin_work_area;
      
      STARTDATE ENDDATE CLASS 
      ---------- ---------- -------------------- 
      17-1?? -03 17-1?? -03 session temperary

       

      会话2:

      SQL> select * from permernate;
      
      A 
      ---------- 
      1 
      2
      
      SQL> select * from admin_work_area;

       

      未选择行.

      会话2看不见会话1中临时表的数据.

      4 ORACLE临时表和SQLSERVER临时表异同

      SQL SERVER临时表

      也可以创建临时表。临时表与永久表相似,但临时表存储在 tempdb 中,当不再使用时会自动删除。 
      有本地和全局两种类型的临时表,二者在名称、可见性和可用性上均不相同。本地临时表的名称以单个数字符号 (#) 打头; 
      它们仅对当前的用户连接是可见的;当用户从 Microsoft? SQL Server? 2000 实例断开连接时被删除。全局临时表的名称以数学符号 

      (##) 打头,创建后对任何用户都是可见的,当所有引用该表的用户从 SQL Server 断开连接时被删除。 
      例如,如果创建名为 employees 的表,则任何人只要在数据库中有使用该表的安全权限就可以使用该表,除非它已删除。 
      如果创建名为 #employees 的本地临时表,只有您能对该表执行操作且在断开连接时该表删除。如果创建名为 ##employees 的全局临时表 

      数据表中的任何用户均可对该表执行操作。如果该表在您创建后没有其他用户使用,则当您断开连接时该表删除。如果该表在您创建 

      后有其他用户使用,则 SQL Server在所有用户断开连接后删除该表 

      不同: 

      1. SQL SERVER临时表是一种”内存表”,表是存储在内存中的.ORACLE临时表除非执行DROP TABLE,否则表定义会保留在数据字典中. 

      2. SQL SERVER临时表不存在类似ORACLE临时表 事务级别 上的功能. 

      3 SQL SERVER本地临时表(#) 与 ORACLE的会话级别临时表类似,但是在会话退出的时候,ORACLE不会删除表. 

      4 SQL SERVER的全局临时表(##) 是指多个连接共享同一片内存.当没有指针引用该内存区域时,SQL SERVER自动释放全局临时表. 

      5 由于ORACLE不是一种 内存中的数据库. 所以如果ORACLE类似SQL SERVER 频繁的对临时表进行建立和删除,必定会影响性能. 
      所以ORACLE会保留临时表的定义直到用户DROP TABLE. 

      6 在ORACLE中,如果需要多个用户共享一个表(类似SQL SERVER的全局临时表##).则可以利用永久表, 

      并且在表中添加一些可以唯一标识用户的列.利用触发器和视图.当用户退出的时候,根据该登陆用户的唯一信息删除相应的表中的数据. 

      这种方法给ORACLE带来了一定量的负载.

       



      我们都知道,全局临时表GTT分为两种,一种是transaction level,一种是session level,
      分别通过on commit delete rows/preserve rows实现,其中session level表示在本sessoin
      数据有效,相同session内,之前事务操作的数据,对于后续的操作都可见,而事务级的GTT表示
      一旦事务结束(commit)那么立即delete,相同session 的后续操作看不到之前事务操作。
      在9i阶段可以使用GATHER_TABLE_STATS调用来收集统计信息须传入参数GATHER_TEMP为TRUE,
      10g开始oracle对于普通表和GTT收集统计信息并没有特殊处理,都是通过GATHER_TABLE_STATS
      存储过程来收集,但是由于上述的两种GTT特殊性,收集统计信息有特殊性:

      1.对于session level的,因为GTT数据并不持久化,存在session 隔离性,需要在当前session 收集,
      若是通过另起窗口(新session)收集统计信息会不成功,原因就是收集统计信息的session 没有数据,
      自然也收集不到统计信息了。

      2.对于transaction level的,即便是当前session 收集,因为GATHER_TABLE_STATS会先执行默认提交,
      所以数据就自动删除,自然也就没有数据可收集了。所以针对这种情景,oracle 有官方note 403587.1介绍
      下面就是移花接木办法来收集事务级GTT的步骤
      1. create a PRESERVE ROWS table
      SQL> create global temporary table TT(I number) on commit preserve rows;
      2. populate with representative data
      SQL> insert into TT select rownum from dba_objects where rownum<1000;
      3. gather stats
      SQL> exec dbms_stats.gather_table_stats(null,'TT');
      4. create a STAT table
      SQL> exec dbms_stats.create_stat_table(null,'TTSTATS');
      5. export the stats from the PRESERVE ROWS table
      SQL> exec dbms_stats.export_table_stats(null,'TT',null,'TTSTATS',null,true);
      6. truncate then drop the PRESERVE ROWS table
      SQL> truncate table TT;
      SQL> drop table TT;
      7. now create the real temporary table (defined using DELETE ROWS - the default)
      SQL> create global temporary table TT(I number);
      8. finally import the stats exported from the STAT table
      SQL> exec dbms_stats.import_table_stats(null,'TT',null,'TTSTATS',null,true);

      3.在12c版本,oracle已经进步改善了对这种transaction level GTT的统计信息收集,
      也就是说GATHER_TABLE_STATS收集统计信息的时候不会默认发起commit,这样就不会
      破坏当前session的事务完整性,收集统计信息的存储过程就可以看到当前session的
      数据情况并收集统计信息。
      下面是一个简单的测试过程:
      3.1.创建transaction level GTT
      Create Global Temporary Table maob_temp  (a number,b varchar2(100)) On Commit delete Rows; <<delete Rows
      Table created.

      3.2.插入数据
      insert into maob_temp select rownum,object_name from dba_objects where rownum<1000;
      SQL>

      999 rows created.

      3.3.收集统计信息
      exec dbms_stats.gather_table_stats(user,'MAOB_TEMP');
      SQL>
      PL/SQL procedure successfully completed.

      3.4.check是否数据已经被删除
       select count(*)from maob_temp;
      SQL>
        COUNT(*)
      ----------
             999

      3.5.查看统计信息是否已经收集成功 
      SQL> select TABLE_NAME,NUM_ROWS,BLOCKS,SCOPE from DBA_TAB_STATISTICS where owner='MAOB' AND TABLE_NAME='MAOB_TEMP';

      TABLE_NAME    NUM_ROWS BLOCKS SCOPE
      --------------------------------------
      MAOB_TEMP    0      0 SHARED
      MAOB_TEMP  999      4 SESSION <<<<

      注意:这一步要在和上述步骤相同的session执行,因为12c的这个新功能默认对GTT收集统计信息是session scope的,也就是说统计信息也是
      session 隔离的,其他session 看不到这个session收集的统计信息,若是变成传统的shared scope,那么仍然会默认先commit再收集
      统计信息并记录数据字典表,供其他session 使用,对于transaction level仍然存在先commit在收集情况,那么要解决问题,仍需要参考步骤
      2的移花接木办法,但是创建表之后要先指定为shared scope再收集统计信息。
      EXEC DBMS_STATS.SET_TABLE_PREFS (NULL,'TT','GLOBAL_TEMP_TABLE_STATS','SHARED');

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/lhrbest/2712278,作者:小麦苗DB宝,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:最全的mysql常用语句大全

      下一篇:MySQL数据库中where条件查询(比较运算符查询、逻辑运算符查询、模糊查询、范围查询、空判断查询)

      相关文章

      2025-05-14 10:03:05

      Oracle数据库用户权限分析

      Oracle数据库用户权限分析

      2025-05-14 10:03:05
      Oracle , 分析 , 数据库 , 权限 , 用户
      2025-05-09 09:21:53

      Oracle 11g系列:数据库

      创建Oracle数据库的最常用工具为Database Configuration Assistant(数据库配置助手),依次选择【开始】|【所有程序】|【Oracle-OraDb11g_home1】|【Configuration and Migration Tools】|【Database Configuration Assistant】命令。

      2025-05-09 09:21:53
      Oracle , ORCL , 导入 , 导出 , 数据库
      2025-05-09 09:21:53

      Oracle控制语句(if , loop , while , for)

      Oracle控制语句(if , loop , while , for)

      2025-05-09 09:21:53
      Oracle , 控制 , 语句
      2024-12-27 08:00:32

      oracle 11.2.0.4 asm单实例不随系统启动而自动开启

      oracle 11.2.0.4 asm单实例不随系统启动而自动开启

      2024-12-27 08:00:32
      Oracle , 开启 , 自动 , 集群
      2024-12-20 07:47:46

      Oracle游标的使用及性能优化

      在使用Oracle数据库进行开发时,游标是一个非常重要的工具。游标允许我们逐行处理查询结果集,对于需要逐条记录进行操作的场景非常适用。

      2024-12-20 07:47:46
      Oracle , 使用 , 游标 , 示例
      2024-12-20 07:45:21

      Oracle数据库学习入门教程

      在数据库领域中,Oracle数据库无疑是最受欢迎和广泛应用的之一。本文将详细解释为何我们选择Oracle数据库学习,并通过入门教程为大家提供一个系统而简明的学习路径。

      2024-12-20 07:45:21
      Oracle , SQL , 学习 , 数据库
      2024-12-18 08:28:12

      Oracle中decode函数详解

      Oracle数据库中的DECODE函数,这是一种强大的条件表达式,经常用于数据查询和转换。让我们一起详细了解DECODE函数的使用方法和实际应用场景。

      2024-12-18 08:28:12
      Oracle , 函数 , 存储 , 条件 , 查询 , 示例
      2024-12-11 06:20:04

      详细分析Oracle数据类型与Java类型对应原则

      在Java中,与Oracle数据库中的数据类型对应的是Java的数据类型,通常通过JDBC(Java Database Connectivity)来实现

      2024-12-11 06:20:04
      java , Java , Oracle , 使用 , 数据 , 数据库 , 类型
      2024-12-06 06:23:00

      Oracle数据库教程:入门到精通

      Oracle数据库是市场上最强大的关系数据库管理系统之一。无论是大数据分析、企业级应用还是高性能交易系统,Oracle都能提供卓越的性能和可靠性。

      2024-12-06 06:23:00
      Oracle , 数据库
      2024-12-06 06:21:05

      Oracle中序列Sequence详解

      在数据库设计和管理中,生成唯一标识是一个至关重要的环节。Oracle数据库中的Sequence(序列)是一项强大的工具,用于生成递增或递减的唯一标识,保障数据表中的每一行都有独特的标识符。

      2024-12-06 06:21:05
      Oracle , 序列
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5243639

      查看更多

      最新文章

      Oracle数据库用户权限分析

      2025-05-14 10:03:05

      Oracle 11g系列:数据库

      2025-05-09 09:21:53

      Oracle控制语句(if , loop , while , for)

      2025-05-09 09:21:53

      Oracle游标的使用及性能优化

      2024-12-20 07:47:46

      Oracle数据库学习入门教程

      2024-12-20 07:45:21

      Oracle数据库教程:入门到精通

      2024-12-06 06:23:00

      查看更多

      热门文章

      Oracle用SQL打印日历

      2023-06-14 09:13:43

      CentOS 7中安装Oracle JDK1.8环境

      2023-05-18 09:33:22

      【Tomcat】Oracle JDK与Apache Tomcat的版本兼容性关系

      2023-06-06 05:54:30

      【WebLogic】Oracle发布WebLogic中间件2022年第1季度安全公告

      2023-06-08 06:16:02

      【DB笔试面试761】在Oracle中,DG中GAP有几种解决方案?

      2023-06-16 06:12:34

      【DB笔试面试759】在Oracle中,如果主库丢失归档文件,那么物理DG如何恢复?

      2023-06-16 06:12:34

      查看更多

      热门标签

      数据库 mysql 字符串 数据结构 MySQL 算法 redis oracle java sql python 数据 索引 SQL 查询
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      Oracle的SYS用户登录报权限不足(ORA-01031: insufficient privileges)

      Oracle中的三种Join 方式

      Oracle instr函数

      【DB笔试面试759】在Oracle中,如果主库丢失归档文件,那么物理DG如何恢复?

      Oracle数据库教程:入门到精通

      Oracle游标的定义与使用

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号