在 Oracle 临时表上放置索引安全吗?

发布于 2024-07-22 16:36:08 字数 185 浏览 11 评论 0原文

我读过,不应分析临时表,因为它会破坏其他表的统计信息。 指数怎么样? 如果我在程序运行期间在表上放置索引,使用该表的其他程序会受到该索引的影响吗?

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

没有一个回复具有权威性,因此我提供上述贿赂。

I have read that one should not analyze a temp table, as it screws up the table statistics for others. What about an index? If I put an index on the table for the duration of my program, can other programs using the table be affected by that index?

Does an index affect my process, and all other processes using the table?
or Does it affect my process alone?

None of the responses have been authoritative, so I am offering said bribe.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

新一帅帅 2024-07-29 16:36:09

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

select /*+ DYNAMIC_SAMPLING (3) */ val
来自索引测试
其中 val = 1;

请参阅询问 Tom

You can also use the dynamic sampling hint (10g):

select /*+ DYNAMIC_SAMPLING (3) */ val
from index_test
where val = 1;

See Ask Tom

拥有 2024-07-29 16:36:09

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

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

会话 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>

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

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

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

You cannot create an index on a temporary table while it is used by another session, so answer is: No, it cannot affect any other process, because it is not possible.

An existing Index affects only your current session, because for any other session the temporary table appears empty, so it cannot access any index values.

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

Session 2 (while session 1 is still connected):

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>

Back to session 1:

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

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

still failing, you first have to disconnect session 1 or table has to be truncated.

Session 1:

SQL> truncate table index_test;
Table truncated.
SQL>

Now you can create the index in Session 2:

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

This index of course will be used by any session.

岁月静好 2024-07-29 16:36:08

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

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

将临时表视为由每个进程根据存储在系统字典中的模板即时创建和删除的多个表

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

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

具有足够权限的每个人都可以看到临时表DML(即其布局,包括列名和索引)。

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

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

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

  • 创建两个具有相同列布局的临时表
  • 在其中一个上建立索引
  • 使用索引表或非索引表,具体取决于过程

Does an index effect my process, and all other processes using the table? or Does it effect my process alone?

I'm assuming we are talking of GLOBAL TEMPORARY tables.

Think of a temporary table as of multiple tables that are created and dropped by each process on the fly from a template stored in the system dictionary.

In Oracle, DML of a temporary table affects all processes, while data contained in the table will affect only one process that uses them.

Data in a temporary table is visible only inside the session scope. It uses TEMPORARY TABLESPACE to store both data and possible indexes.

DML for a temporary table (i. e. its layout, including column names and indexes) is visible to everybody with sufficient privileges.

This means that existence of the index will affect your process as well as other processes using the table in sense that any process that modifies data in the temporary table will also have to modify the index.

Data contained in the table (and in the index too), on the contrary, will affect only the process that created them, and will not even be visible to other processes.

IF you want one process to use the index and another one not to use it, do the following:

  • Create two temporary tables with same column layout
  • Index on one of them
  • Use indexed or non-indexed table depending on the process
白色秋天 2024-07-29 16:36:08

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

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

来自:

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

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

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

I assume you're referring to true Oracle temporary tables and not just a regular table created temporarily and then dropped. Yes, it is safe to create indexes on the temp tables and they will be used according to the same rules as a regular tables and indexes.

[Edit]
I see you've refined your question, and here's a somewhat refined answer:

From:

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

"Indexes can be created on temporary tables. They are also temporary and the data in the index has the same session or transaction scope as the data in the underlying table."

If you need the index for efficient processing during the scope of the transaction then I would imagine you'll have to explicitly hint it in the query because the statistics will show no rows for the table.

不及他 2024-07-29 16:36:08

您问的是两个不同的事情:索引和统计数据。
对于索引,是的,您可以在临时表上创建索引,它们将照常维护。

对于统计,我建议您显式设置表的统计信息以表示查询时表的平均大小。 如果您只是让 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

You're asking about two different things, indexes and statistics.
For indexes, yes, you can create indexes on the temp tables, they will be maintained as per usual.

For statistics, I recommend that you explicitly set the stats of the table to represent the average size of the table when queried. If you just let oracle gather stats by itself, the stats process isn't going to find anything in the tables (since by definition, the data in the table is local to your transaction), so it will return inaccurate results.

e.g. you can do:

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

Another tip is that if the size of the temporary table varies greatly, and within your transaction, you know how many rows are in the temp table, you can help out the optimizer by giving it that information. I find this helps out a lot if you are joining from the temp table to regular tables.

e.g., if you know the temp table has about 100 rows in it, you can:

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

儭儭莪哋寶赑 2024-07-29 16:36:08

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

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

这是我运行的测试用例:

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

Well, I tried it out and the index was visible and used by the second session. Creating a new global temporary table for your data would be safer if you really need an index.

You are also unable to create an index while any other session is accessing the table.

Here's the test case I ran:

--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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文