(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 Standard Edition 2 Named User Plus License
Oracle Database Standard Edition 2 Processor License
Oracle Database Personal Edition Named User Plus Software Update License & Support
Oracle Database Personal Edition Named User Plus License
Quest Software. Toad for SQL Server Development Suite
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Компьютерные книги. Рецензии и отзывы
Краткие описания программ и ссылки на них
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100