Индексно–организованные таблицы (IOT). ORA-25188 . Physical rowid и Logical urowid

dbstalker, 24 сентября

Рассмотрим некоторые аспекты использования индексно-организованных таблиц - Index Organized Tables(IOT). Это особый тип таблиц у Oracle. Обычная таблица, создаваемая в вашей базе данных, имеет тип «кучи» (heap) – записи навалены кучей вне зависимости от содержимого. После создания таблицы создается индекс. Когда записи вставляются, то они помещаются в первый доступный блок, который найдет оракл (основываясь на FREELISTS), не придерживаясь никакого определенного порядка. В индексно-организованных таблицах записи размещаются в порядке определенном первичным ключом, который вы установили.

Проведем некоторые тесты:

create table trading_history ( 
    trade_id    varchar2(10), 
    trade_date    date, 
    closing_price    number(12,2), 
    lots        number, 
    put_call    varchar2(1), 
    constraint  th_pk primary key(trade_id, trade_date) 
) 
organization index 
tablespace indx 
/ 

Для IOT наличие primary key обязательно и его удалить или сделать disable невозможно:

SQL> alter table trading_history drop constraint th_pk; 
alter table trading_history drop constraint th_pk 
* 
ERROR at line 1: 
ORA-25188: cannot drop/disable/defer the primary key constraint for 
index-organized tables or sorted hash cluster 

SQL> alter table trading_history disable constraint th_pk; 
alter table trading_history disable constraint th_pk 
* 
ERROR at line 1: 
ORA-25188: cannot drop/disable/defer the primary key constraint for 
index-organized tables or sorted hash cluster 

SQL> create table trading_history ( 
  2   trade_id varchar2(10), 
  3   trade_date date, 
  4   closing_price number(12,2), 
  5   lots  number, 
  6   put_call varchar2(1), 
  7   constraint  th_pk primary key(trade_id, trade_date) deferrable 
  8  ) 
  9  organization index 
10  tablespace indx 
11  / 
create table trading_history ( 
* 
ERROR at line 1: 
ORA-25188: cannot drop/disable/defer the primary key constraint for index-organized tables or sorted hash cluster. 

Во всех этих случаях получаем ошибку ORA-25188.

Теперь посмотрим в словарь на информацию о нашей таблице

SQL>  select table_name, tablespace_name, iot_type 
  2   from user_tables 
  3   where table_name = 'TRADING_HISTORY' 
  4  / 

TABLE_NAME      TABLESPACE IOT_TYPE 
--------------- ---------- ------------ 
TRADING_HISTORY            IOT 

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

SQL> select segment_name, segment_type, tablespace_name 
  2  from user_segments 
  3  where segment_name = 'TRADING_HISTORY' 
  4  / 

no rows selected 

Однако для индекса сегменты есть:

SQL> select segment_name, segment_type, tablespace_name 
  2  from user_segments 
  3  where segment_name = 'TH_PK' 
  4  / 

SEGMENT_NA SEGMENT_TYPE       TABLESPACE_NAME 
---------- ------------------ ------------------------------ 
TH_PK      INDEX              INDX 


SQL> select file_id,block_id,blocks from dba_extents where segment_name='TH_PK';

   FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------

         8       2313          4

SQL> alter system dump datafile 8 block min 2313 block max 2316;

System altered.

Фактически индексно –организованная таблица на самом деле является индексом. Отличие такого индекса от обычного B*Tree индекса состоит в том, что в него записываются все колонки (поля) записи, а не только индексируемые как в обычном индексе.

Physical rowids и Logical rowids

Когда вы используете обычную (HEAP) таблицу и создаете индекс на нее, тот индекс использует физический (physical) rowid как указатель на адрес самой записи. Это нормальный ROWID, который мы видим, например, в запросе "select rowid from my_table".

Структура ROWID такова:

6 bytes  -  data object number, the object number of the segment 
3 bytes -  data file number, the datafile in a tablespace. 
6 bytes -  block number 
3 bytes -  the row number 

Для “раскодировки” ROWID используют пакет dbms_rowid.

SQL> select rowid r, 
  2         dbms_rowid.rowid_object(rowid) obj_number, 
  3         dbms_rowid.rowid_relative_fno(rowid) file_number, 
  4         dbms_rowid.rowid_block_number(rowid) block_number, 
  5         dbms_rowid.rowid_row_number(rowid) row_number 
  6  from t 
  7  where rownum <= 5 
  8  / 

R                  OBJ_NUMBER FILE_NUMBER BLOCK_NUMBER ROW_NUMBER 
------------------ ---------- ----------- ------------ ---------- 
AAANI9AAEAAAAMUAAA      53821           4          788          0 
AAANI9AAEAAAAMUAAB      53821           4          788          1 
AAANI9AAEAAAAMUAAC      53821           4          788          2 
AAANI9AAEAAAAMUAAD      53821           4          788          3 
AAANI9AAEAAAAMUAAE      53821           4          788          4 

Для индексно- организованных таблиц используется несколько иной подход: сразу создается индекс, основанный на первичном ключе и включающий прочие колонки записи. Фактически есть только индекс, а таблицы в виде кучи нет. Поэтому для такого типа индекса оракл не использует физический ROWID. Вместо его используется UROWID – универсальный или логический rowid.

SQL> select rowid as urowid, x, y 
  2  from t1 
  3  where rownum <=5; 

UROWID                                             X          Y 
----------------------------------------- ---------- ---------- 
*BAGAAHQCwQP+                                      2          2 
*BAGAAHQCwQT+                                      3          3 
*BAGAAHQCwQX+                                      4          2 
*BAGAAHQCwQb+                                      5          2 
*BAGAAHQCwQf+                                      6          6 

Структура UROWID отличается от структуры ROWID, поэтому очевидно, что пакет dbms_rowid для IOT не может быть использован.

Некоторые особенности IOT таблиц.

Нужно обратить внимание на одну важную вещь, которая происходит при переносе (перестройке) таблицы. Так как куча использует physical rowid, операция MOVE для таблицы делает индексы некорректными - таблица физически переносится, размещение записей изменяется, а значит rowid -ы, которые используются в индексах, становятся непригодными. Их нужно перестраивать. Для IOT такого не происходит, так как эти таблицы основаны на primary keys и перемещение IOT не изменяет primary key. А значит UROWID.

Важное различие между HEAP и IOT состоит в том, что IOT содержит не только индексируемые колонки, а и все колонки таблицы. Для IOT когда вы запрашиваете определенный набор записей, будет использован primary keys. И по нему вы уже сразу получите все колонки, которые вероятно вам будут нужны и будут выданы в результат. Когда используется HEAP, осуществляется поиск по индексу, берется ключ, который подходит для вашего фильтра, используется rowid из вашего индекса для того, чтобы обратиться к записям самой таблицы и выбрать уже все колонки, которые вам нужны. Получается, что для обычных таблиц нужно выполнить две операции, чтобы выбрать все необходимые нам колонки по заданному фильтру. Хотя, возможно оптимизатор будет использовать только индекс, если он содержит все необходимые колонки.

Предназначение IOT - взять ключи и сами данные одновременно, избегая индексно-табличного поиска. И минимизировать операции ввода вывода в ходе этого процесса. IOT хорошо использовать, если часто нужен доступ к проиндексированным колонкам и еще к нескольким (2 или3) другим колонкам. Например, это хорошо для таблиц, где вам нужно определить атрибуты подобные цене товара, зная первичный ключ.

Если вы знаете, что будете использовать больше-чаще другие колонки таблицы помимо проиндексированных колонок, то вероятнее лучше использовать HEAP.

источник

 

Новый комментарий

Я не спамер: введите суму 3+2



 

От авторов блога

О Блоге - прочитай перед началом.

Задать вопрос и получить ответ - уже решено 94 вопросов

Глоссарий - список терминов и сокращений


 
 

Бизнес форум

Последние темы:

Спутниковое тв
21 января, 3 ответа