(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Системная информация в индексах

Источник: ln

Эта статья посвящена обсуждению структуры записей в индексах (помните, я собирался часть выпусков посвящать индексам ;). По мотивам ответа Тома Кайта на вопрос, заданный 14 июня 2003 года.

Системная информация в индексах

Том,

После анализа индекса (analyze ... validate) я поделил LF_ROWS_LEN на LF_ROWS и обнаружил значение на 12 байтов больше, чем длина ключа. Я ожидал увеличения только на 6 байтов - размер rowid, а откуда взялись другие 6 байтов? Может, я неправильно считаю?

SQL> analyze index IDX_TBLACCOUNT validate structure;

Index analyzed

SQL> select * from index_stats;

HEIGHT                 3             
BLOCKS                 18056         
NAME                   IDX_TBLACCOUNT
PARTITION_NAME         
LF_ROWS                5796880       
LF_BLKS                16868         
LF_ROWS_LEN            75359440      
LF_BLK_LEN             7996          
BR_ROWS                16867         
BR_BLKS                57            
BR_ROWS_LEN            237396        
BR_BLK_LEN             8028          
DEL_LF_ROWS            7655          
DEL_LF_ROWS_LEN        99515         
DISTINCT_KEYS          20            
MOST_REPEATED_KEY      4228703       
BTREE_SPACE            135334124     
USED_SPACE             75596836      
PCT_USED               56            
ROWS_PER_KEY           289844        
BLKS_GETS_PER_ACCESS   144925.5      
PRE_ROWS               0             
PRE_ROWS_LEN           0             

LF_ROWS_LEN/LF_ROWS = 75359440/5796880 = 13

Длина столбца - 1 байт (varchar2(1)).

SQL> select * from user_ind_columns where index_name = 'IDX_TBLACCOUNT';

INDEX_NAME       IDX_TBLACCOUNT
TABLE_NAME       TBLACCOUNT    
COLUMN_NAME      AC_STATUS     
COLUMN_POSITION  1             
COLUMN_LENGTH    1             
DESCEND          ASC           

SQL> select * from user_tab_columns where table_name='TBLACCOUNT' and column_name='AC_STATUS';

TABLE_NAME           TBLACCOUNT
COLUMN_NAME          AC_STATUS 
DATA_TYPE            VARCHAR2  
DATA_TYPE_MOD                 
DATA_TYPE_OWNER               
DATA_LENGTH          1         
DATA_PRECISION                
DATA_SCALE                    
NULLABLE             Y         
COLUMN_ID            67        
DEFAULT_LENGTH                
DATA_DEFAULT                  
NUM_DISTINCT         17        
LOW_VALUE            30        
HIGH_VALUE           74        
DENSITY              0.05882352
NUM_NULLS            0         
NUM_BUCKETS          1         
LAST_ANALYZED        6/14/2003 
SAMPLE_SIZE          235526        
CHARACTER_SET_NAME   CHAR_CS   
CHAR_COL_DECL_LENGTH 1         
GLOBAL_STATS         NO        
USER_STATS           NO        
AVG_COL_LEN          1         

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

SQL> analyze index idx_tblaccount_stssch validate structure;

Index analyzed

SQL> select * from index_stats;

HEIGHT               3                    
BLOCKS               18845                
NAME                 IDX_TBLACCOUNT_STSSCH
PARTITION_NAME                         
LF_ROWS              5794493              
LF_BLKS              17096                
LF_ROWS_LEN          121620457            
LF_BLK_LEN           7996                 
BR_ROWS              17095                
BR_BLKS              53                   
BR_ROWS_LEN          390029               
BR_BLK_LEN           8028                 
DEL_LF_ROWS          5268                 
DEL_LF_ROWS_LEN      110621               
DISTINCT_KEYS        22291                
MOST_REPEATED_KEY    553444               
BTREE_SPACE          137125100            
USED_SPACE           122010486            
PCT_USED             89                   
ROWS_PER_KEY         259.94764703         
BLKS_GETS_PER_ACCESS 133.473823516217     
PRE_ROWS             0                    
PRE_ROWS_LEN         0                    

LF_ROWS_LEN/LF_ROWS = 121620457/5794493 = 20.99 (у нас 12880 строк со значениями NULL в первом столбце)

Получаем снова DATE (7 байтов) + разделитель? - прокомментируй, пожалуйста, (1 байт) + varchar2(1) (1 байт) = 9 байтов.

12 байтов использовано системой для своих целей.

SQL> select * from user_tab_columns where table_name='TBLACCOUNT' and column_name='AC_SCHEDULETIME';

TABLE_NAME           TBLACCOUNT     
COLUMN_NAME          AC_SCHEDULETIME
DATA_TYPE            DATE           
DATA_TYPE_MOD                    
DATA_TYPE_OWNER                  
DATA_LENGTH          7              
DATA_PRECISION                   
DATA_SCALE                       
NULLABLE             Y              
COLUMN_ID            72             
DEFAULT_LENGTH                   
DATA_DEFAULT                     
NUM_DISTINCT         4941           
LOW_VALUE            78640714110101 
HIGH_VALUE           C7C70C1F0E0201 
DENSITY              0.00020238     
NUM_NULLS            12880          
NUM_BUCKETS          1              
LAST_ANALYZED        6/14/2003      
SAMPLE_SIZE          235526 
CHARACTER_SET_NAME               
CHAR_COL_DECL_LENGTH             
GLOBAL_STATS         NO             
USER_STATS           NO             
AVG_COL_LEN          7              

Ответ Тома Кайта

Системой используется 4/5 байтов.

Столбец типа varchar2 имеет начальный байт длины, так что varchar2(1) занимает, минимум, 2 байта. Надо также учесть индикатор null-значения. Значение rowid тоже хранится как "строка" (с начальными байтами длины).

Итак, для ключа типа varchar2(1) имеем:
1 байт "длины", 1 байт "данных", 1 байт "длины rowid", 6 байтов данных rowid = 9 байтов.

При тестировании я получаю 12 байтов на строку в версии 9203 для ОС RedHat Linux на платформе Intel. Это очень легко определить:

ops$tkyte@ORA920> create table t ( x varchar2(20) );

Table created.

ops$tkyte@ORA920> create index t_idx on t(x);

Index created.

ops$tkyte@ORA920> begin
  2      for i in 1 .. 20
  3      loop
  4          execute immediate 'truncate table t';
  5
  6          insert into t
  7          select rpad(chr(rownum),i,chr(rownum))
  8            from all_objects
  9           where rownum <= 255;
 10
 11          execute immediate 'analyze index t_idx validate structure';
 12          for x in ( select lf_rows_len, lf_rows, lf_rows_len/lf_rows bytes_per_entry
 13                       from index_stats )
 14          loop
 15              dbms_output.put_line
 16              ( 'Width = ' // i // ' lf_rows_len = ' // x.lf_rows_len //
 17                ' bytes/entry = ' // x.bytes_per_entry );
 18          end loop;
 19      end loop;
 20  end;
 21  /

Width = 1 lf_rows_len = 3315 bytes/entry = 13
Width = 2 lf_rows_len = 3570 bytes/entry = 14
Width = 3 lf_rows_len = 3825 bytes/entry = 15
Width = 4 lf_rows_len = 4080 bytes/entry = 16
Width = 5 lf_rows_len = 4335 bytes/entry = 17
Width = 6 lf_rows_len = 4590 bytes/entry = 18
Width = 7 lf_rows_len = 4845 bytes/entry = 19
Width = 8 lf_rows_len = 5100 bytes/entry = 20
Width = 9 lf_rows_len = 5355 bytes/entry = 21
Width = 10 lf_rows_len = 5610 bytes/entry = 22
Width = 11 lf_rows_len = 5865 bytes/entry = 23
Width = 12 lf_rows_len = 6120 bytes/entry = 24
Width = 13 lf_rows_len = 6375 bytes/entry = 25
Width = 14 lf_rows_len = 6630 bytes/entry = 26
Width = 15 lf_rows_len = 6885 bytes/entry = 27
Width = 16 lf_rows_len = 7140 bytes/entry = 28
Width = 17 lf_rows_len = 7395 bytes/entry = 29
Width = 18 lf_rows_len = 7650 bytes/entry = 30
Width = 19 lf_rows_len = 7905 bytes/entry = 31
Width = 20 lf_rows_len = 8160 bytes/entry = 32

PL/SQL procedure successfully completed.

Итак, при длине 20 мы имеем:


длина     1+
данные   20+
длина     1+
данные    6
         --
      32-28 = 4

В каждой строке - на 4 байта "больше", а если добавить еще один большой столбец:

ops$tkyte@ORA920> drop table t;

Table dropped.

ops$tkyte@ORA920> create table t ( x varchar2(20), y char(100) default 'x' );

Table created.

ops$tkyte@ORA920> create index t_idx on t(x,y);

Index created.

ops$tkyte@ORA920> begin
  2      for i in 1 .. 20
  3      loop
  4          execute immediate 'truncate table t';
  5
  6          insert into t (x)
  7          select rpad(chr(rownum),i,chr(rownum))
  8            from all_objects
  9           where rownum <= 255;
 10
 11          execute immediate 'analyze index t_idx validate structure';
 12          for x in ( select lf_rows_len, lf_rows, lf_rows_len/lf_rows bytes_per_entry
 13                       from index_stats )
 14          loop
 15              dbms_output.put_line
 16              ( 'Width = ' // i // ' lf_rows_len = ' // x.lf_rows_len //
 17                ' bytes/entry = ' // x.bytes_per_entry );
 18          end loop;
 19      end loop;
 20  end;
 21  /

Width = 1 lf_rows_len = 29070 bytes/entry = 114
Width = 2 lf_rows_len = 29325 bytes/entry = 115
Width = 3 lf_rows_len = 29580 bytes/entry = 116
Width = 4 lf_rows_len = 29835 bytes/entry = 117
Width = 5 lf_rows_len = 30090 bytes/entry = 118
Width = 6 lf_rows_len = 30345 bytes/entry = 119
Width = 7 lf_rows_len = 30600 bytes/entry = 120
Width = 8 lf_rows_len = 30855 bytes/entry = 121
Width = 9 lf_rows_len = 31110 bytes/entry = 122
Width = 10 lf_rows_len = 31365 bytes/entry = 123
Width = 11 lf_rows_len = 31620 bytes/entry = 124
Width = 12 lf_rows_len = 31875 bytes/entry = 125
Width = 13 lf_rows_len = 32130 bytes/entry = 126
Width = 14 lf_rows_len = 32385 bytes/entry = 127
Width = 15 lf_rows_len = 32640 bytes/entry = 128
Width = 16 lf_rows_len = 32895 bytes/entry = 129
Width = 17 lf_rows_len = 33150 bytes/entry = 130
Width = 18 lf_rows_len = 33405 bytes/entry = 131
Width = 19 lf_rows_len = 33660 bytes/entry = 132
Width = 20 lf_rows_len = 33915 bytes/entry = 133

PL/SQL procedure successfully completed.

Можно ожидать:


длина     1
данные   20
длина     1  (да, CHAR - всего лишь VARCHAR2, дополненный пробелами - длина тоже хранится)
данные  100
длина     1
данные    6
        ---
  133 - 129 = 4 дополнительных байта

Комментарий читателя от 15 июня 2003 года

Интересно, зачем для значения rowid длина, - что, идентификаторы строк могут быть переменной длины? И откуда берутся эти 4 байта? Зачем они нужны?

Ответ Тома Кайта

Они просто "есть" (то есть, нужны)

Комментарий читателя от 18 июня 2003 года

Вот дамп блока:

row#0[536] flag: -----, lock: 0
col 0; len 20; (20):  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
col 1; len 6; (6):  02 40 03 8d 00 00
row#1[566] flag: -----, lock: 0
col 0; len 20; (20):  02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
col 1; len 6; (6):  02 40 03 8d 00 01
row#2[596] flag: -----, lock: 0
col 0; len 20; (20):  03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
col 1; len 6; (6):  02 40 03 8d 00 02
row#3[626] flag: -----, lock: 0
col 0; len 20; (20):  04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04
col 1; len 6; (6):  02 40 03 8d 00 03

Судя по нему, каждая строка занимает 30 байтов: строки начинаются со смещений 536, 566, 596, 626... Не мог бы ты объяснить, откуда взялись 2 байта в твоих результатах?

Ответ Тома Кайта

Я не занимаюсь интерпретацией результатов дампов. Вы изучаете "отчет" о блоке, а не сам блок. См. поля flags, row#, и т.д. Считайте, что это "данные, которые необходимы серверу для управления данными пользователя"

Все просто - сколько надо, столько система и использует.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 16.03.2010 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Oracle Database Personal Edition Named User Plus Software Update License & Support
Oracle Database Personal Edition Named User Plus License
Oracle Database Standard Edition 2 Named User Plus License
Oracle Database Standard Edition 2 Processor License
ReSharper Ultimate - Commercial annual subscription
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Adobe Photoshop: алхимия дизайна
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100