Безопасно ли размещать индекс для временной таблицы Oracle? - PullRequest
12 голосов
/ 02 июня 2009

Я прочитал, что не следует анализировать временную таблицу, так как это приводит в замешательство статистику таблицы для других. Как насчет индекса? Если я помещу в таблицу индекс на время действия моей программы, могут ли другие программы, использующие эту таблицу, быть затронуты этим индексом?

Влияет ли индекс на мой процесс и на все другие процессы, использующие таблицу? или это влияет только на мой процесс?

Ни один из ответов не был достоверным, поэтому я предлагаю указанную взятку.

Ответы [ 6 ]

13 голосов
/ 08 июня 2009

Влияет ли индекс на мой процесс и на все другие процессы, использующие таблицу? или это влияет только на мой процесс?

Я предполагаю, что мы говорим о GLOBAL TEMPORARY таблицах.

Представьте себе временную таблицу как несколько таблиц, которые создаются и удаляются каждым процессом на лету из шаблона, хранящегося в системном словаре .

В Oracle, DML из temporary table влияет на все процессы, в то время как данные, содержащиеся в таблице, влияют только на один процесс, который их использует.

Данные в temporary table видны только внутри области действия сеанса. Он использует TEMPORARY TABLESPACE для хранения данных и возможных индексов.

DML для temporary table (т.е. его макет, включая имена столбцов и индексы) виден всем, имеющим достаточные привилегии.

Это означает, что существование индекса повлияет на ваш процесс, а также на другие процессы, использующие таблицу, в том смысле, что любой процесс, который изменяет данные в temporary table, также должен будет модифицировать индекс.

Данные , содержащиеся в таблице (и в индексе тоже), напротив, будут влиять только на процесс, который их создал, и даже не будут видны другим процессам.

Если вы хотите, чтобы один процесс использовал индекс, а другой не использовал его, сделайте следующее:

  • Создание двух temporary tables с одинаковым расположением столбцов
  • Индекс по одному из них
  • Используйте индексированную или неиндексированную таблицу в зависимости от процесса
9 голосов
/ 02 июня 2009

Я предполагаю, что вы имеете в виду настоящие временные таблицы Oracle, а не просто обычную таблицу, созданную временно и затем удаленную. Да, безопасно создавать индексы для временных таблиц, и они будут использоваться по тем же правилам, что и обычные таблицы и индексы.

[Изменить] Я вижу, вы уточнили свой вопрос, и вот несколько уточненный ответ:

От:

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

"Индексы могут создаваться во временных таблицах. Они также являются временными , и данные в индексе имеют ту же область сеанса или транзакции, что и данные в базовой таблице ."

Если вам нужен индекс для эффективной обработки во время транзакции, тогда я думаю, вам придется явно указать его в запросе, потому что статистика не покажет строки для таблицы.

6 голосов
/ 03 июня 2009

Вы спрашиваете о двух разных вещах, индексах и статистике. Для индексов да, вы можете создавать индексы для временных таблиц, они будут поддерживаться как обычно.

Для статистики я рекомендую явно установить статистику таблицы, чтобы она представляла средний размер таблицы при запросе. Если вы просто позволите 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

2 голосов
/ 08 июня 2009

Ну, я попробовал, и индекс был виден и использовался во втором сеансе. Создание новой глобальной временной таблицы для ваших данных будет более безопасным, если вам действительно нужен индекс.

Вы также не можете создать индекс, пока любой другой сеанс обращается к таблице.

Вот контрольный пример, который я запустил:

--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;
1 голос
/ 09 июня 2009

Вы также можете использовать подсказку динамической выборки (10 г):

выберите / * + DYNAMIC_SAMPLING (3) * / val из index_test где val = 1;

Смотри Спроси Тома

0 голосов
/ 03 декабря 2013

Вы не можете создать индекс для временной таблицы, пока он используется другим сеансом, поэтому ответ: Нет, это не может повлиять на любой другой процесс, потому что это невозможно.

Существующий индекс влияет только на ваш текущий сеанс, поскольку для любого другого сеанса временная таблица выглядит пустой, поэтому она не может получить доступ к каким-либо значениям индекса.

Сессия 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>

Этот индекс, конечно, будет использоваться любым сеансом.

...