在 Oracle 临时表上放置索引安全吗?
我读过,不应分析临时表,因为它会破坏其他表的统计信息。 指数怎么样? 如果我在程序运行期间在表上放置索引,使用该表的其他程序会受到该索引的影响吗?
索引是否会影响我的进程以及使用该表的所有其他进程? 或者它是否仅影响我的流程?
没有一个回复具有权威性,因此我提供上述贿赂。
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您还可以使用动态采样提示(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
当临时表被另一个会话使用时,您不能在临时表上创建索引,所以答案是:不,它不能影响任何其他进程,因为这是不可能的。
现有索引仅影响当前会话,因为对于任何其他会话,临时表都显示为空,因此它无法访问任何索引值。
会话 1:
会话 2(会话 1 仍处于连接状态时):
返回会话 1:
会话 2:
仍然失败,您首先必须断开会话 1 的连接,否则表必须被截断。
会话 1:
现在您可以在会话 2 中创建索引:
当然该索引将被任何会话使用。
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:
Session 2 (while session 1 is still connected):
Back to session 1:
Session 2:
still failing, you first have to disconnect session 1 or table has to be truncated.
Session 1:
Now you can create the index in Session 2:
This index of course will be used by any session.
我假设我们正在谈论
GLOBAL TEMPORARY
表。将临时表视为由每个进程根据存储在系统字典中的模板即时创建和删除的多个表。
在 Oracle 中,临时表的 DML 会影响所有进程,而表中包含的数据只会影响使用它们的一个进程。
临时表中的数据仅在会话范围内可见。 它使用
TEMPORARY TABLESPACE
来存储数据和可能的索引。具有足够权限的每个人都可以看到
临时表
的DML
(即其布局,包括列名和索引)。这意味着索引的存在将影响您的进程以及使用该表的其他进程,因为任何修改
临时表
中的数据的进程也必须修改索引。相反,表中包含的数据(以及索引中的数据)只会影响创建它们的进程,甚至对其他进程不可见。
如果您希望一个进程使用索引而另一个进程不使用索引,请执行以下操作:
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 atemporary 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 usesTEMPORARY TABLESPACE
to store both data and possible indexes.DML
for atemporary 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:
temporary tables
with same column layout我假设您指的是真正的 Oracle 临时表,而不仅仅是临时创建然后删除的常规表。 是的,在临时表上创建索引是安全的,并且将根据与常规表和索引相同的规则使用它们。
[编辑]
我看到您已经改进了您的问题,这里有一个稍微改进的答案:
来自:
“索引可以在临时表上创建。它们也是临时的并且索引中的数据与数据具有相同的会话或事务范围在基础表中。”
如果您需要索引在事务范围内进行有效处理,那么我想您必须在查询中显式提示它,因为统计信息将显示表中没有行。
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:
"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.
您问的是两个不同的事情:索引和统计数据。
对于索引,是的,您可以在临时表上创建索引,它们将照常维护。
对于统计,我建议您显式设置表的统计信息以表示查询时表的平均大小。 如果您只是让 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
好吧,我尝试了一下,索引是可见的,并被第二个会话使用。 如果您确实需要索引,则为数据创建新的全局临时表会更安全。
当任何其他会话正在访问该表时,您也无法创建索引。
这是我运行的测试用例:
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: