Практически обработку текстовой информации в Oracle Text обеспечивает текстовый индекс. Содержательно он организует хранение «обращенного списка», который по предъявленному поисковому слову выдает список пар <документ, словоместо>. Для этого он хранит список документов, позиций словоформ в документах и одно или несколько индексируемых слов в каждой позиции.
Технически текстовый индекс устроен сложнее обычных B-древовидного или же поразрядного индексов хотя бы тем, что реализован сразу группой объектов и группой структур хранения. Вэтомлегкоудостовериться:
38. SQL> COLUMN object_name FORMAT A30
39. SQL> COLUMN object_type FORMAT A30
40. SQL> COLUMN segment_name FORMAT A30
41. SQL> COLUMN segment_type FORMAT A30
42. SQL> SELECT object_name, object_type FROM user_objects ORDER BY 2, 1;
OBJECT_NAME OBJECT_T
------------------------------ --------
DOCS_VC2DOC_IDX INDEX
DR$DOCS_VC2DOC_IDX$X INDEX
SYS_IOT_TOP_34422 INDEX
SYS_IOT_TOP_34427 INDEX
SYS_LOB0000034419C00006$$ LOB
SYS_LOB0000034424C00002$$ LOB
DOCS TABLE
DR$DOCS_VC2DOC_IDX$I TABLE
DR$DOCS_VC2DOC_IDX$K TABLE
DR$DOCS_VC2DOC_IDX$N TABLE
DR$DOCS_VC2DOC_IDX$R TABLE
43. SQL> SELECT segment_name, segment_type FROM user_segments ORDER BY 2, 1;
SEGMENT_NAME SEGMENT_TYPE
------------------------------ --------------
DR$DOCS_VC2DOC_IDX$X INDEX
SYS_IOT_TOP_34422 INDEX
SYS_IOT_TOP_34427 INDEX
SYS_IL0000034419C00006$$ LOBINDEX
SYS_IL0000034424C00002$$ LOBINDEX
SYS_LOB0000034419C00006$$ LOBSEGMENT
SYS_LOB0000034424C00002$$ LOBSEGMENT
DOCS TABLE
DR$DOCS_VC2DOC_IDX$I TABLE
DR$DOCS_VC2DOC_IDX$R TABLE
В обоих запросах все объекты БД и структуры хранения, кроме DOCS, принадлежат текстовому индексу. Точнее, в результате команды CREATE INDEX docs_vc2doc_idx ... индекс DOCS_VC2DOC_IDX (типа DOMAIN) появился только как логический объект в БД; технически его реализуют четыре возникшие служебные таблицы:
Таблица DR$DOCS_VC2DOC_IDX$I . Хранит перечень всех словоформ, попавших в индекс, внутренний номер документа («DOCID») и список позиций словоформ в документе. Вторичные, связанные с ней объекты:
индекс DR$DOCS_VC2DOC_IDX$X (обычный, типа NORMAL),
сегменты типа LOBSEGMENT и LOBINDEX для хранения данных поля TOKEN_INFO типа BLOB.
Таблица DR$DOCS_VC2DOC_IDX$K . Хранит соответствие DOCID адресу ROWID строки с текстом или ссылкой на текст. Индексно-организованная таблица, хранится в структуре индекса.
Таблица DR$DOCS_VC2DOC_IDX$R . Хранит список для обратного поиска: ROWID по DOCID. Вторичные, связанные с ней объекты:
сегменты типа LOBSEGMENT и LOBINDEX для хранения данных поля DATA типа BLOB.
Таблица DR$DOCS_VC2DOC_IDX$N . Хранит список удаленных документов (DOCID) пополняющийся при оптимизации текстового индекса. Индексно-организованная таблица, хранится в структуре индекса.
44. Пример выдачи из таблицы DR$DOCS_VC2DOC_IDX$I.
SQL> SELECT token_text, token_count FROM dr$docs_vc2doc_idx$i;
TOKEN_TEXT TOKEN_COUNT
---------------------------------------------------------------- -----------
БРАТЬ 1
ЗВЕЗДА 1
ИМЕЕТ 1
ЛАМПУ 2
ЛУЧИК 1
МАЛЕНЬКАЯ 1
МАЛЕНЬКУЮ 1
МАША 1
НЕЛЬЗЯ 1
ЭТУ 1
45. Еще одно отличие текстового индекса от обычного в том, что он не правится автоматически при изменении документа. Например, выполните обновление:
SQL> UPDATE docs SET vc2doc = 'Эту лампу нельзя лапать' WHERE doc_id = 3;
46. Завершите транзакцию: SQL> COMMIT;
47. SQL> SELECT token_text, token_count FROM dr$docs_vc2doc_idx$i;
TOKEN_TEXT TOKEN_COUNT
---------------------------------------------------------------- -----------
БРАТЬ 1
ЗВЕЗДА 1
ИМЕЕТ 1
ЛАМПУ 2
ЛУЧИК 1
МАЛЕНЬКАЯ 1
МАЛЕНЬКУЮ 1
МАША 1
НЕЛЬЗЯ 1
ЭТУ 1
48. Как видите новое слово лапать не появилось!
49. В силу громоздкости текстового индекса сведения о необходимых исправлениях собираются в отдельной таблице, а сама правка выполняется по мере надобности вручную.
SQL>SELECT pnd_index_name, pnd_rowid FROM ctx_user_pending;
PND_INDEX_NAME PND_ROWID
------------------------------ ------------------
DOCS_VC2DOC_IDX AAAIZxAAJAAACHGAAC
50. SQL>EXECUTE CTX_DDL.SYNC_INDEX ( 'docs_vc2doc_idx' )
51. SQL> SELECT token_text, token_count FROM dr$docs_vc2doc_idx$i;
БРАТЬ 1
ЗВЕЗДА 1
ИМЕЕТ 1
ЛАМПУ 2
ЛУЧИК 1
МАЛЕНЬКАЯ 1
МАЛЕНЬКУЮ 1
МАША 1
НЕЛЬЗЯ 1
ЭТУ 1
ЛАПАТЬ 1
52. Как видите теперь индекс обновлен!
53. Можно и по другому: SQL> UPDATE docs SET vc2doc = 'Эту лампу и выключатель нельзя лапать' WHERE doc_id = 3;
54. SQL> COMMIT;
55. SQL> SELECT token_text, token_count FROM dr$docs_vc2doc_idx$i;
Выключатель не появился!
56. Обновитеиндекс: SQL>ALTER INDEX docs_vc2doc_idx REBUILD;
57. SQL> SELECT token_text, token_count FROM dr$docs_vc2doc_idx$i;
Выключатель есть!