Індексування обраних рядків, Інші СУБД, Бази даних, статті

Ця коротка стаття присвячена індексуванню рядків таблиці, що задовольняють деякій умові.


Чи можна індексувати тільки обрані рядки?


Привіт, Том!

Можливо, я відстав від часу – все ще використовую версію 8.1.7, – але мені просто цікаво, чи не можна створити індекси тільки по обраним рядках. Наприклад, коли в індексується стовпці багато порожніх значень і, як я бачив в безлічі різних додатків, з якими доводилося працювати, абсолютно точно відомо, що рядки з порожніми значеннями в цьому стовпці (за цим індексом) вибирати ніколи не будуть.


Мені здається, що можна було б заощадити місце на диску (і в пам’яті, наскільки я розумію), якщо б можна було вимагати індексувати тільки рядки з конкретними значеннями (або навпаки – не ідексіровать такі рядки).


Відповідь Тома Кайта


Ну, по-перше, якщо запис індексу (звичайного, не на основі бітових карт – прим. В.К.) цілком складається зі значень NULL, Вона взагалі ніколи не потрапляє в індекс!


Розглянемо приклад:

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

Table created.

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

Index created.

ops$tkyte@ORA920> insert into t select null from all_users;

51 rows created.

ops$tkyte@ORA920> analyze index t_idx validate structure;

Index analyzed.

ops$tkyte@ORA920> select name, lf_rows from index_stats;

NAME LF_ROWS
—————————— ———-
T_IDX 0


Цей індекс – порожній, у ньому нічого немає. Помістимо в таблицю непустих рядок, і:

ops$tkyte@ORA920> insert into t values ( 1 );

1 row created.

ops$tkyte@ORA920> analyze index t_idx validate structure;

Index analyzed.

ops$tkyte@ORA920> select name, lf_rows from index_stats;

NAME LF_ROWS
—————————— ———-
T_IDX 1


ми, нарешті, отримаємо запис. Якщо потім встановити у всіх рядках непусті значення:

ops$tkyte@ORA920> update t set x = rownum;

52 rows updated.

ops$tkyte@ORA920> analyze index t_idx validate structure;

Index analyzed.

ops$tkyte@ORA920> select name, lf_rows from index_stats;

NAME LF_ROWS
—————————— ———-
T_IDX 53


всі вони опиняться в індексі …


Тепер, щоб проіндексувати вибірково, можна використовувати CASE (Або вбудовані функції DECODE і NVL в тих версіях Oracle, де CASE ще не підтримувався – прим. В.К. ) Зі складним умовою для ідентифікації необхідних значень – в даному випадку, я буду індексувати всі рядки, в яких x менше 25:


ops$tkyte@ORA920> create index t_idx2 on t( case when x < 25 then x end );

Index created.

ops$tkyte@ORA920> analyze index t_idx2 validate structure;

Index analyzed.

ops$tkyte@ORA920> select name, lf_rows from index_stats;

NAME LF_ROWS
—————————— ———-
T_IDX2 24


Тільки ці рядки опинилися в індексі. Далі, можна (і, по-моєму, треба) використовувати уявлення, щоб приховати складність запитів через цей індекс:

ops$tkyte@ORA920> create or replace view v as select x, case when x < 25 then x end another_x from t;

View created.

ops$tkyte@ORA920> analyze table t compute statistics;

Table analyzed.

ops$tkyte@ORA920> set autotrace traceonly explain
ops$tkyte@ORA920> select * from v where another_x = 5;

Execution Plan
———————————————————-
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=2)
1 0 TABLE ACCESS (BY INDEX ROWID) OF “T” (Cost=3 Card=1 Bytes=2)
2 1 INDEX (RANGE SCAN) OF “T_IDX2” (NON-UNIQUE) (Cost=2 Card=1)

ops$tkyte@ORA920> set autotrace off

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*