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


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.