Як складається індекс люцену?


95

Я прочитав якийсь документ про Люцену; також я прочитав документ за цим посиланням ( http://lucene.sourceforge.net/talks/pisa ).

Я насправді не розумію, як Lucene індексує документи, і не розумію, які алгоритми Lucene використовує для індексації?

У наведеному вище посиланні сказано, що Lucene використовує цей алгоритм для індексації:

  • інкрементний алгоритм:
    • підтримувати стек сегментних індексів
    • створити індекс для кожного вхідного документа
    • виштовхувати нові індекси в стек
    • нехай b = 10 - коефіцієнт злиття; М = 8

for (size = 1; size < M; size *= b) {
    if (there are b indexes with size docs on top of the stack) {
        pop them off the stack;
        merge them into a single index;
        push the merged index onto the stack;
    } else {
        break;
    }
}

Як цей алгоритм забезпечує оптимізоване індексування?

Чи використовує Люцен алгоритм B-дерева або будь-який інший алгоритм, подібний до цього, для індексації - чи він має певний алгоритм?


Більшість відповідей тут правильні, що спочатку Lucene створює інвертований індекс, але це не пояснює ключового моменту того, як цей термін індекс згодом здійснюється пошук (і, я вважаю, те, про що насправді просив OP). Тож нижче, будь-ласка, знайдіть нову відповідь на це досить давнє запитання, яке, сподіваємось, забезпечує кращу інформацію.
— fnl

1
Оновив свою відповідь ще раз, оскільки поточні відповіді (включаючи мою!) Насправді не задовільні, щоб відповісти на основні два запитання ОП (як Lucene забезпечує оптимізовану індексацію та за яким саме алгоритмом - Skip-List, а не B-Tree, До речі). Сподіваюся, мої остаточні оновлення тепер правильно відповідатимуть на актуальне питання!
— fnl

Відповіді:


54

Тут є досить хороша стаття: https://web.archive.org/web/20130904073403/http://www.ibm.com/developerworks/library/wa-lucene/

Редагувати 12/2014: оновлено до заархівованої версії через видалення оригіналу, мабуть, найкращою пізнішою альтернативою є http://lucene.apache.org/core/3_6_2/fileformats.html

Існує ще найновіша версія за адресою http://lucene.apache.org/core/4_10_2/core/org/apache/lucene/codecs/lucene410/package-summary.html#package_description , але, схоже, в ній менше інформації ніж старший.

У двох словах, коли люцен індексує документ, він розбиває його на кілька термінів. Потім він зберігає терміни у файлі індексу, де кожен термін пов’язаний з документами, що його містять. Ви можете сприймати це як щось на зразок хеш-таблиці.

Терміни генеруються за допомогою аналізатора, який пов'язує кожне слово з його кореневою формою. Найпопулярнішим алгоритмом стемінгу для англійської мови є алгоритм стереотипу Porter: http://tartarus.org/~martin/PorterStemmer/

Коли запит видається, він обробляється за допомогою того самого аналізатора, який був використаний для побудови індексу, а потім використовувався для пошуку відповідних термінів в індексі. Це забезпечує перелік документів, які відповідають запиту.


Дякуємо за вашу відповідь та посилання. Але я чув, що у проекту «Люцен» є спеціальний стример під назвою «Сніжок»? Ви щось про це чули?
— M.Amrollahi

Це інше запитання: Дивіться lucidimagination.com/search/ ... Окрім цього, бачачи шаблон вашого запитання, я пропоную вам прочитати книгу „Lucene in Action“: manning.com/hatcher2 (Перше видання трохи застаріле, але може бути знайдено у версії мертвого дерева. Друге видання можна придбати як електронну книгу).
— Yuval F

5
Ви можете змінити свою відповідь, перше посилання, яке є посиланням IBM, не знайдено :)
— Adelin

Крім того, як поля вводять ціле зображення? Якщо запит стосується конкретного поля, як і в який момент люцен знає, що термін, який вказує на документ, знаходиться не в документі, а всередині запитуваного поля?
— Левон Тамразов

44

У двох словах, Lucene створює інвертований індекс, використовуючи Skip-Lists на диску , а потім завантажує відображення для індексованих термінів в пам’ять за допомогою датчика скінченого стану (FST). Однак зауважте, що Lucene не (обов'язково) завантажує всі проіндексовані терміни в оперативну пам'ять , як це описав Майкл МакКендлесс, сам автор індексної системи Lucene. Зверніть увагу, що за допомогою Skip-Lists індекс можна переходити від одного звернення до іншого, роблячи можливими такі речі, як запити набору та, зокрема, діапазону (подібно до B-Trees). А запис Вікіпедії про індексування списків пропуску також пояснює, чому реалізацію списку пропусків Люцена називають багаторівневоюSkip-List - по суті, щоб зробити O(log n)можливим пошук (знову ж таки, подібно до B-Trees).

Отже, як тільки інвертований (терміновий) індекс - який базується на структурі даних Skip-List - побудований з документів, індекс зберігається на диску. Lucene потім завантажує (як уже було сказано: можливо, тільки деякі) ці терміни в кінцевих станів перетворювача , в реалізації FST вільно натхненний по Morfologick .

Майкл МакКендлесс (також) робить досить гарну і стислу роботу, пояснюючи, як і чому Люцен використовує (мінімальний ациклічний) FST для індексації термінів, які Луцен зберігає в пам'яті, по суті як "а" SortedMap<ByteSequence,SomeOutput>, і дає базову ідею про те, як працюють ФСТ (тобто, як FST ущільнює послідовності байтів [тобто індексовані терміни], щоб зробити використання пам’яті цього відображення підлінійним). І він вказує на статтю, яка описує конкретний алгоритм FST , який також використовує Люцен.

Для тих , кому цікаво , чому Lucene використовує пропуск списки, в той час як більшість баз даних використовують (B +) - і / або (В) -дерева, погляньте на в правому SO відповіді щодо цього питання (скіп-списки проти B-дерева). Ця відповідь дає досить хороше, глибоке пояснення - по суті, не стільки робить паралельні оновлення індексу "більш придатними" (оскільки ви можете вирішити не перебалансувати B-дерево відразу, тим самим отримуючи приблизно таку ж паралельну продуктивність, як Skip-List), а навпаки, Skip-Lists позбавляють вас від необхідності працювати над операцією балансування (із затримкою чи ні) (в кінцевому підсумку) необхідні B-Trees (насправді, як показує відповідь / посилання, між B-Trees та [багаторівневим] Skip-Lists, мабуть, дуже мала різниця в продуктивності, якщо будь-який з них "зроблено правильно").


1
Afaik вони використовують Skip List замість B-дерева, щоб зменшити кількість пошуків диска, оскільки частина Skip List знаходиться в пам'яті і дуже мало дискового вводу-виводу потрібно при обробці індексу
— Антон,

24

Здається, ваше питання більше стосується злиття індексів, аніж самого індексування.

Процес індексації досить простий, якщо ви ігноруєте деталі низького рівня. Люцен утворюють те, що називається "перевернутий індекс" з документів. Отже, якщо надходить документ із текстом "Бути чи не бути" та id = 1, інвертований індекс буде виглядати так:

[to] → 1
[be] → 1
[or] → 1
[not] → 1

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

Насправді, звичайно, все складніше:

  • Люцен може пропускати деякі слова на основі конкретного даного Аналізатора;
  • слова можуть бути попередньо оброблені за допомогою алгоритму стерміну для зменшення гнучкості мови;
  • Список проводки може містити не тільки ідентифікатори документів, але також зміщення даного слова всередині документа (потенційно кілька екземплярів) та деяку іншу додаткову інформацію.

Є набагато більше ускладнень, які не так важливі для базового розуміння.

Важливо розуміти, що індекс люцену додається лише . У певний момент часу програма вирішує зафіксувати (опублікувати) всі зміни в індексі. Люцен закінчує всі сервісні операції індексом і закриває, щоб він був доступний для пошуку. Після коміту індекс в основному незмінний. Цей індекс (або індексна частина) називається сегментом . Коли Lucene виконує пошук запиту, він здійснює пошук у всіх доступних сегментах.

Тож виникає питання - як ми можемо змінити вже проіндексований документ ?

Нові документи або нові версії вже проіндексованих документів індексуються в нових сегментах, а старі версії втрачають силу в попередніх сегментах за допомогою так званого списку вбивств . Список вбивств - це єдина частина фіксованого індексу, яка може змінюватися. Як можна здогадатися, ефективність індексів з часом падає, оскільки старі індекси можуть містити переважно видалені документи.

Тут відбувається злиття. Об’єднання - це процес об’єднання кількох індексів, щоб зробити загальний індекс ефективнішим. Що відбувається в основному під час злиття - це поточні документи, скопійовані в новий сегмент, і старі сегменти повністю видаляються.

Використовуючи цей простий процес, Lucene може підтримувати індекс у належній формі з точки зору ефективності пошуку.

Сподіваюся, це допоможе.


1
Тож для пошуку найсучасніших результатів спочатку чи розпочнеться пошук з перегляду найновіших сегментів? Тож лише для уточнення - припустимо, документ оновлений. Старіша версія документа додається до списку вбивств, тоді будь-які збіги, знайдені у старих сегментах, видаляються із результатів пошуку, якщо їх ідентифікатор документа збігається з ідентифікатором у списку вбивств?
— Joel B

2
Так, ти маєш рацію. Єдине, про що слід згадати - це остаточний порядок, визначений за допомогою правил сортування (індекс релевантності у тривіальному випадку), тому порядок пошуку сегментів не є актуальним.
— Денис Баженов

12

Це інвертований індекс , але він не вказує, яку структуру він використовує. Формат індексу в люцені має повну інформацію.
Почніть із "Зведення розширень файлів".

Спочатку ви помітите, що в ньому йдеться про різні різні індекси. Наскільки я міг помітити, жоден із них не використовує строго кажучи B-дерево , але є схожість - вищевказані структури дійсно нагадують дерева.


1
Інверсований індекс Люцена базується на пропущеному списку, а не на B-дереві. Все-таки деревоподібна структура в дуже широкому розумінні, але лише для того, щоб бути повною - наприклад, див. Це запитання SO. Використання Люценом списку пропусків та цього SO-питання, чому скіп-списки можуть бути кращими над B-деревами .
— fnl
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.