将索引放在Oracle临时表上是否安全?

时间:2009-06-02 18:20:01

标签: oracle indexing temp-tables

我已经读过,不应该分析临时表,因为它会破坏其他人的表统计信息。索引怎么样?如果我在程序的持续时间内在表上放置一个索引,那么使用该表的其他程序是否会受到该索引的影响?

索引会影响我的进程以及使用该表的所有其他进程吗? 或者它是否会影响我的过程?

没有一个回复是权威的,所以我提供贿赂。

6 个答案:

答案 0 :(得分:13)

  

索引是否会影响我的流程以及使用该表的所有其他流程?或者它会影响我的过程吗?

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

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

Oracle中,DML的{​​{1}}会影响所有进程,而表中包含的数据只会影响使用它们的一个进程。

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

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

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

相反,表中(以及索引中)中包含的

数据将仅影响创建它们的进程,甚至不会对其他进程可见。

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

  • 创建两个具有相同列布局的temporary table
  • 其中一个指数
  • 根据流程使用索引或非索引表

答案 1 :(得分:9)

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

[编辑]  我看到你提炼了你的问题,这是一个有点精炼的答案:

自:

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

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

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

答案 2 :(得分:6)

你问的是两个不同的东西,索引和统计数据。 对于索引,是的,您可以在临时表上创建索引,它们将按照惯例进行维护。

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

e.g。你可以这样做:

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

答案 3 :(得分:2)

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

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

这是我跑的测试案例:

--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;

答案 4 :(得分:1)

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

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

请参阅Ask Tom

答案 5 :(得分:0)

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

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

第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>

第二节:

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>

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

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

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