【问题标题】:Is it safe to put an index on an Oracle Temporary Table?在 Oracle 临时表上放置索引是否安全?
【发布时间】:2010-10-30 18:39:47
【问题描述】:

我已经读到不应该分析临时表,因为它会破坏其他人的表统计信息。索引呢?如果我在程序执行期间在表上放置索引,使用该表的其他程序会受到该索引的影响吗?

索引是否会影响我的进程以及使用该表的所有其他进程? 还是它会单独影响我的流程?

没有任何回应具有权威性,因此我提供了上述贿赂。

【问题讨论】:

    标签: oracle indexing temp-tables


    【解决方案1】:

    索引是否会影响我的进程以及使用该表的所有其他进程?还是它会单独影响我的流程?

    我假设我们正在谈论GLOBAL TEMPORARY 表。

    将一个临时表想象为多个表,这些表由每个进程从存储在系统字典中的模板动态创建和删除。

    在Oracle 中,DML 中的temporary table 会影响所有进程,而表中包含的数据只会影响使用它们的一个进程。

    temporary table 中的数据仅在会话范围内可见。它使用TEMPORARY TABLESPACE 来存储数据和可能的索引。

    DML 用于temporary table(即其布局,包括列名和索引)对具有足够权限的每个人都是可见的。

    这意味着索引的存在将影响您的进程以及使用该表的其他进程,因为任何修改temporary table 中数据的进程也将不得不修改索引。

    相反,

    数据包含在表中(以及索引中),只会影响创建它们的进程,甚至不会对其他进程可见。

    如果您希望一个进程使用索引而另一个进程不使用它,请执行以下操作:

    • 创建两个具有相同列布局的temporary tables
    • 其中之一的索引
    • 根据进程使用索引表或非索引表

    【讨论】:

      【解决方案2】:

      我假设您指的是真正的 Oracle 临时表,而不仅仅是临时创建然后删除的常规表。是的,在临时表上创建索引是安全的,它们将按照与常规表和索引相同的规则使用。

      [编辑] 我看到你已经提炼了你的问题,这里有一个稍微提炼的答案:

      发件人:

      Oracle® Database Administrator's Guide
      10g Release 2 (10.2)
      Part Number B14231-02
      

      “可以在临时表上创建索引。它们也是临时的并且索引中的数据与基础表中的数据具有相同的会话或事务范围。”

      如果您需要索引在事务范围内进行有效处理,那么我想您必须在查询中明确提示它,因为统计信息不会显示表的行。

      【讨论】:

      • 索引将存在于所有会话中(因此,如果它是唯一索引并且他们期望非唯一数据,或者即使它只是减慢插入速度,可能会影响它们的处理并可能给它们带来问题/更新)。此外,添加/删除索引会在表上短暂锁定同样,您可以在临时表上收集统计信息,但假设它们适用于该表上的所有查询,这些查询可能适合您的情况,也可能不适合您的情况。
      • >Gary 不,索引的存储方式与表完全相同 - 在每个会话中单独存储,因此即使索引是唯一的,您也不会在会话之间发生冲突。显然添加/删除索引会锁定表,但是您多久添加/删除索引?是的,统计信息全局应用于临时表,这就是为什么有时您需要在查询 GTT 时使用 CARDINALITY 提示。
      • 好吧,Gary 和 Jeff,你们都理解这个问题,但似乎有不同的意见。
      • 意见并不重要。结果很重要 - 测试并查看!
      • 顺便说一句,我制作了许多应用程序,这些应用程序特别依赖于 GTT 上的索引对于每个会话都是本地的这一事实。
      【解决方案3】:

      您问的是两个不同的东西,索引和统计信息。 对于索引,是的,您可以在临时表上创建索引,它们将照常维护。

      对于统计信息,我建议您明确设置表的统计信息,以表示查询时表的平均大小。如果您只是让 oracle 自己收集统计信息,则统计过程不会在表中找到任何内容(因为根据定义,表中的数据是您的事务本地的),因此它会返回不准确的结果。

      例如你可以这样做:

      exec dbms_stats.set_table_stats(user, 'my_temp_table', numrows=>10, numblks=>4)

      另一个提示是,如果临时表的大小变化很大,并且在您的事务中,您知道临时表中有多少行,您可以通过向优化器提供该信息来帮助优化器。如果您从临时表加入常规表,我发现这会很有帮助。

      例如,如果您知道临时表中有大约 100 行,您可以:

      SELECT /*+ CARDINALITY(my_temp_table 100) */ * FROM my_temp_table

      【讨论】:

      • 我只是在询问索引。我了解统计数据。临时表可能一次被多个进程使用。将统计数据放在桌面上可能会产生负面影响。
      • 我将测试基数提示的使用。非常感谢+1
      【解决方案4】:

      好吧,我试了一下,第二个会话可见并使用了索引。如果您确实需要索引,为您的数据创建一个新的全局临时表会更安全。

      当任何其他会话正在访问该表时,您也无法创建索引。

      这是我运行的测试用例:

      --first session
      create global temporary table index_test (val number(15))
      on commit preserve rows;
      
      create unique index idx_val on index_test(val);
      
      --second session
      insert into index_test select rownum from all_tables;
      select * from index_test where val=1;
      

      【讨论】:

        【解决方案5】:

        也可以使用动态采样提示(10g):

        选择 /*+ DYNAMIC_SAMPLING (3) */ val 来自 index_test 其中 val = 1;

        见Ask Tom

        【讨论】:

          【解决方案6】:

          当临时表被另一个会话使用时,您不能在临时表上创建索引,因此答案是:不,它不会影响任何其他进程,因为这是不可能的。

          现有索引仅影响您当前的会话,因为对于任何其他会话,临时表显示为空,因此它无法访问任何索引值。

          第 1 节:

          SQL> create global temporary table index_test (val number(15)) on commit preserve rows;
          Table created.
          SQL> insert into index_test values (1);
          1 row created.
          SQL> commit;
          Commit complete.
          SQL>
          

          会话 2(会话 1 仍处于连接状态):

          SQL> create unique index idx_val on index_test(val);
          create unique index idx_val on index_test(val)
                                         *
          ERROR at line 1:
          ORA-14452: attempt to create, alter or drop an index on temporary table already in use
          SQL>
          

          返回会话 1:

          SQL> delete from index_test;
          1 row deleted.
          SQL> commit;
          Commit complete.
          SQL>
          

          第 2 节:

          SQL> create unique index idx_val on index_test(val);
          create unique index idx_val on index_test(val)
                                         *
          ERROR at line 1:
          ORA-14452: attempt to create, alter or drop an index on temporary table already in use
          SQL>
          

          仍然失败,您首先必须断开会话 1,否则必须截断表。

          第 1 节:

          SQL> truncate table index_test;
          Table truncated.
          SQL>
          

          现在您可以在 Session 2 中创建索引:

          SQL> create unique index idx_val on index_test(val);
          Index created.
          SQL>
          

          这个索引当然会被任何会话使用。

          【讨论】:

            猜你喜欢
            • 2013-05-21
            • 2017-10-02
            • 2023-03-27
            • 1970-01-01
            • 1970-01-01
            • 2012-12-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多