Частный фильтр - Quotient filter

А частный фильтр является компактным вероятностный структура данных используется для проверки того, элемент является членом набор (ан примерный запрос участника фильтр, AMQ). Запрос вызовет ответ, в котором будет указано, что элемент определенно не входит в набор или что элемент, вероятно, входит в набор. Первый результат является окончательным; т.е., тест не генерирует ложные отрицания. Но с последним результатом существует некоторая вероятность, ε, что тест вернет «элемент находится в наборе», когда на самом деле элемент отсутствует в наборе (т.е., а ложный положительный результат ). Существует компромисс между ε, частотой ложных срабатываний и размером хранилища; увеличение размера памяти фильтра уменьшает ε. Другие операции AMQ включают «вставку» и «необязательное удаление». Чем больше элементов добавлено в набор, тем больше вероятность ложных срабатываний.

Фильтр приблизительного запроса члена (AMQ), используемый для ускорения ответов в системе хранения значений ключей. Пары ключ-значение хранятся на диске, который имеет медленное время доступа. Решения о фильтре AMQ принимаются намного быстрее. Однако, когда фильтр сообщает о положительном результате, совершаются некоторые ненужные обращения к диску (чтобы отсеять ложные срабатывания). Общая скорость ответа с фильтром AMQ лучше, чем без него. Однако использование AMQ-фильтра для этой цели увеличивает использование памяти.

Типичное применение фильтров частных и других фильтров AMQ - служить прокси для ключей в база данных на диске. Когда ключи добавляются в базу данных или удаляются из нее, фильтр обновляется, чтобы отразить это. Любой поиск сначала обращается к быстрому фильтру частного, а затем просматривает базу данных (предположительно гораздо медленнее), только если фильтр частного сообщает о наличии ключа. Если фильтр возвращает значение «Отсутствие», известно, что ключ отсутствует в базе данных без выполнения каких-либо обращений к диску.

Частный фильтр имеет обычные операции AMQ вставки и запроса. Кроме того, его также можно объединить и изменить размер без повторного хеширования исходных ключей (тем самым избегая необходимости доступа к этим ключам из вторичного хранилища). Это свойство приносит пользу некоторым видам лог-структурированные деревья слияния.

История

Компактный хеш-таблица лежащий в основе факторного фильтра был описан Клири в 1984 году.[1] Первое известное упоминание об использовании структуры в качестве фильтра AMQ принадлежит Пагу. et. al. в 2005 году.[2] В 2009 году Диллинджер и Манолиос оптимизировали метаданные структуры, добавили размещение дополнительных элементов на месте и применили структуру к явному состоянию. проверка модели.[3] В 2011 году Бендер и другие. придумал название «частный фильтр», описал несколько вариантов с различными компромиссами при кодировании метаданных, показал, как объединить и изменить размер частных фильтров, представил оптимизированную для записи версию частного фильтра для использования на диске и применил структуру к хранилищу базы данных проблемы.[4][5]В 2017 году Панди и другие. описал версию, которая использует аппаратные инструкции по манипулированию битами для повышения производительности, поддерживает одновременные обновления и добавляет поддержку для привязки счетчика переменного размера к каждому элементу.[6]

Описание алгоритма

Частный фильтр основан на хеш-таблица в котором записи содержат только часть ключа плюс некоторые дополнительные биты метаданных. Эти биты используются, чтобы иметь дело с случаем, когда разные ключи хешируют одну и ту же запись таблицы. Напротив, другие типы хэш-таблиц, которые справляются с такими конфликтами путем связывания с областями переполнения, не являются компактными, потому что накладные расходы из-за связывания могут превышать хранилище, используемое для хранения ключа.[1] В частном фильтре a хэш-функция генерирует п-битовый отпечаток пальца. В р младшие значащие биты называются остатком, а q = п - р наиболее значимые биты называются частным, отсюда и название частное (придумано Knuth.[7]) В хеш-таблице 2q слоты.

Для некоторого ключа d который хеширует отпечаток пальца dЧАС, пусть его частное будет dQ а остальные будут dр.QF попытается сохранить остаток в слоте d.Q, который известен как канонический слотОднако канонический слот может уже быть занят, потому что несколько ключей могут хешировать один и тот же отпечаток пальца - жесткое столкновение- или потому что, даже когда отпечатки клавиш различны, они могут иметь одинаковое отношение - мягкое столкновение. Если канонический слот занят, то остаток сохраняется в некотором слоте справа.

Как описано ниже, алгоритм вставки гарантирует, что все отпечатки пальцев, имеющие одинаковое частное, хранятся в смежных слотах. Такой набор отпечатков пальцев определяется как пробег.[4] Обратите внимание, что первый отпечаток запуска может не занять свой канонический слот, если запуск был принудительно перемещен вправо каким-то запуском влево.

Однако запуск, первый отпечаток которого занимает канонический слот, указывает на начало кластер.[4] Первоначальный запуск и все последующие запуски составляют кластер, который заканчивается в незанятом слоте или в начале другого кластера.

Три дополнительных бита используются для восстановления отпечатка слота. Они выполняют следующие функции:

is_occupied
устанавливается, когда слот является каноническим слотом для некоторого ключа, хранящегося (где-то) в фильтре (но не обязательно в этом слоте).
is_continuation
устанавливается, когда слот занят, но не первым остатком в прогоне.
is_shifted
устанавливается, когда остаток в слоте не находится в его каноническом слоте.

Различные комбинации имеют следующее значение:

is_occupied
is_continuation
is_shifted
смысл
000Пустой слот
001Слот удерживает начало запуска, которое было сдвинуто с его канонического слота.
010не используется.
011Слот удерживает продолжение запуска, которое было перемещено из его канонического слота.
100Слот удерживает начало запуска, которое находится в его каноническом слоте.
Это тоже начало кластера.
101Слот удерживает начало запуска, которое было сдвинуто с его канонического слота.
Также существует прогон, для которого это канонический слот, но он сдвинут вправо.
110не используется.
111Слот удерживает продолжение запуска, которое было перемещено из его канонического слота.
Также существует прогон, для которого это канонический слот, но он сдвинут вправо.

Искать

Мы можем проверить, содержит ли факторный фильтр некоторый ключ, d, следующим образом.[4]

Мы хэшируем ключ для получения отпечатка пальца, dЧАС, который мы затем разбиваем на q бит старшего порядка, dQ, которые составляют его частное и младшие r битов, dр, составляющие его остаток. Слот dQ - канонический слот ключа. Этот слот пуст, если его три бита метаданных ложны. В этом случае фильтр не содержит ключа.

Если канонический слот занят, мы должны найти пробег частного. Набор слотов, которые содержат остатки, принадлежащие одному и тому же частному, хранятся непрерывно, и они составляют прогон частного. Первый слот в прогоне может быть каноническим слотом, но также возможно, что весь прогон был сдвинут вправо из-за вторжения слева другого прогона.

Чтобы найти частный пробег, мы должны сначала определить начало кластера. Кластер состоит из непрерывного набора запусков. Начиная с канонического слота частного, мы можем сканировать влево, чтобы найти начало кластера, а затем сканировать вправо, чтобы найти пробег частного.

Сканируем влево в поисках слота с is_shifted ложно. Это указывает на начало кластера. Затем мы сканируем вправо, постоянно подсчитывая количество прогонов, которые мы должны пропустить. Каждый слот слева от канонического слота, имеющий is_occupied набор указывает другой прогон, который нужно пропустить, поэтому мы увеличиваем счетчик бега. Каждый слот, имеющий is_continuation Чисто указывает начало другого прогона, то есть конец предыдущего прогона, поэтому мы уменьшаем счетчик бега. Когда текущий счетчик достигает нуля, мы сканируем частное. Мы можем сравнить остаток в каждом слоте в прогоне с dр. Если найден, мы сообщаем, что ключ (вероятно) находится в фильтре, в противном случае мы сообщаем, что ключ определенно не находится в фильтре.

Пример поиска

Пример фильтра частных, показывающий порядок вставки элементов б, е, ж, c, d и а

Возьмем, например, поиск элемента е. См. Состояние 3 на рисунке. Мы бы вычислили Неужели он), разбиваем его на остаток, eр и его частное eQ, что равно 4. При сканировании слева от слота 4 мы обнаруживаем три is_occupied слоты под индексами 4, 2 и 1, что указывает на eQЗапуск - это 3-й запуск в кластере. Сканирование останавливается на слоте 1, который мы определяем как начало кластера, поскольку он не пуст и не сдвинут. Теперь мы должны сканировать прямо до 3-го прогона. Начало пробега обозначается значком is_continuation ложь. Первый прогон находится с индексом 1, второй - с 4 и третий - с 5. Мы сравниваем остаток, удерживаемый в каждом слоте в прогоне, который начинается с индекса 5. В этом прогоне только один слот, но в нашем примере его остаток равен eр, указывая, что е действительно является членом фильтра с вероятностью 1 - ε.

Вставка

Вставка следует по пути, аналогичному поиску, пока мы не убедимся, что ключ определенно не находится в фильтре.[4] В этот момент мы вставляем остаток в слот в текущем прогоне, выбранный для сохранения прогона в отсортированном порядке. Мы сдвигаем вперед остатки в любых слотах кластера в выбранном слоте или после него и обновляем биты слота.

  • Смещение остатка слота не влияет на его is_occupied бит, потому что он относится к слоту, а не к остатку, содержащемуся в слоте.
  • Если мы вставляем остаток в начале существующего прогона, предыдущий остаток сдвигается и становится слотом продолжения, поэтому мы устанавливаем его is_continuation кусочек.
  • Мы устанавливаем is_shifted немного остатка, который мы сдвигаем.

Пример вставки

На рисунке показан факторный фильтр, проходящий через серию состояний по мере добавления элементов. В состоянии 1 были добавлены три элемента. Слот, который занимает каждый из них, образует серию из одного слота, которая также является отдельным кластером.

В состоянии 2 элемента c и d были добавлены. Элемент c имеет частное 1, то же, что и б. Мы предполагаем bр р так ср сдвинут в слот 2 и помечен как продолжение и сдвинут. Элемент d имеет частное 2. Поскольку его канонический слот уже используется, он перемещается в слот 3 и помечен как сдвинут. Кроме того, его канонический слот помечен как занят. Прогоны для частных 1 и 2 теперь составляют кластер.

В состоянии 3 элемента а был добавлен. Его фактор равен 1. Предположим, чторр поэтому остатки в слотах с 1 по 4 должны быть сдвинуты. Слот 2 получает bр и отмечен как продолжение и сдвинут. Слот 5 получает eр и отмечен как сдвинут. Выполнения для коэффициентов 1, 2 и 4 теперь составляют кластер, и наличие этих трех прогонов в кластере обозначается наличием слотов 1, 2 и 4, отмеченных как занят.

Стоимость исполнения

Длина кластера

Бендер[4] утверждает, что кластеры небольшие. Это важно, потому что для поиска и вставки требуется определить начало и длину всего кластера. Если хеш-функция генерирует равномерно распределенные отпечатки пальцев, то длина большинства прогонов равна О(1) и весьма вероятно, что все имеет длину О(бревно м) куда м количество слотов в таблице.[4]

Вероятность ложных срабатываний

Бендер[4] вычисляет вероятность ложного срабатывания (т. е. когда хэш двух ключей приводит к одному и тому же отпечатку пальца) с точки зрения размера остатка хеш-таблицы и коэффициента загрузки. Напомним, что п битовый отпечаток разбивается на q битовое частное, определяющее размер таблицы м = 2q слоты, а р битовый остаток. Коэффициент загрузки это доля занятых слотов п в общее количество слотов м: . Тогда для хорошей хэш-функции приблизительно равна вероятности жесткого столкновения.

Пространство / производительность

Версия фильтра частных Пандей требует меньше места, чем сопоставимый фильтр Блума, когда целевая частота ложных срабатываний меньше 1/64.[6]

Заявление

Частные фильтры являются AMQ и, как таковые, предоставляют многие из тех же преимуществ, что и Фильтры Блума. Большая база данных, например Webtable[8] может состоять из более мелких подтаблиц, каждая из которых имеет связанный фильтр. Каждый запрос распространяется одновременно на все подтаблицы. Если вложенная таблица не содержит запрошенного элемента, ее фильтр может быстро завершить запрос без каких-либо операций ввода-вывода.

Частные фильтры в некоторых приложениях дают два преимущества.

  1. Два частных фильтра можно эффективно объединить, не влияя на их количество ложных срабатываний. Это невозможно с фильтрами Блума.
  2. Несколько дубликатов можно эффективно переносить и их можно удалить.

Пространство, используемое факторными фильтрами, сравнимо с пространством фильтров Блума. Однако фильтры частных можно эффективно объединить в памяти без необходимости повторно вставлять исходные ключи.

Это особенно важно в некоторых системах хранения со структурированными журналами, в которых используется лог-структурированное дерево слияния или LSM-дерево.[9] LSM-дерево на самом деле представляет собой набор деревьев, но рассматривается как единое хранилище значений ключа. Одним из вариантов LSM-дерева является Дерево слияния отсортированных массивов или SAMT.[10] В этом варианте деревья компонентов SAMT называются Wanna-B-деревья. Каждый хочет-B-дерево имеет связанный фильтр частных. Запрос в SAMT направлен только на избранные.B-деревья, о чем свидетельствуют их фильтры частных.

Система хранения данных в нормальном режиме работы компактна SAMT Wanna-B-деревья, сливающиеся меньшего размера Wanna-B-деревья в более крупные и объединение их частных фильтров. Важным свойством частных фильтров является то, что их можно эффективно объединять без необходимости повторно вставлять исходные ключи. Учитывая, что для больших наборов данных Wanna-B-деревья могут не находиться в памяти, доступ к ним для получения исходных ключей может повлечь за собой множество операций ввода-вывода.

По построению значения в частном фильтре хранятся в отсортированном порядке. Каждый прогон связан с определенным значением частного, которое обеспечивает наиболее значительную часть отпечатка пальца, прогоны сохраняются по порядку, и каждый слот в цикле обеспечивает наименее значительную часть отпечатка пальца.

Итак, работая слева направо, можно восстановить все отпечатки пальцев, и результирующий список целых чисел будет отсортирован. Затем слияние двух частных фильтров представляет собой простой вопрос преобразования каждого частного фильтра в такой список, объединения двух списков и использования его для заполнения нового более крупного частного фильтра. Точно так же мы можем уменьшить вдвое или удвоить размер фильтра частных без повторного хеширования ключей, поскольку отпечатки пальцев можно пересчитать, используя только частные и остатки.[4]

Смотрите также

Примечания

  1. ^ а б Клири, Джон Г. (сентябрь 1984 г.). «Компактные хеш-таблицы с двунаправленным линейным зондированием». Транзакции IEEE на компьютерах. 33 (9): 828–834. Дои:10.1109 / TC.1984.1676499. S2CID  195908955.
  2. ^ Паг, Анна; Паг, Расмус; Рао, С. Шриниваса (2005). «Оптимальная замена фильтра Блума» (PDF). Материалы шестнадцатого ежегодного симпозиума ACM-SIAM по дискретным алгоритмам. С. 823–829.
  3. ^ Диллинджер, Питер С .; Манолиос, Панайотис (2009). «Быстрое универсальное хранилище состояний». 16-й Международный семинар SPIN по программному обеспечению для проверки моделей. Спрингер, Конспект лекций по информатике 5578.
  4. ^ а б c d е ж грамм час я Бендер, Майкл А .; Фарач-Колтон, Мартин; Джонсон, Роб; Kuszmaul, Bradley C .; Медедович, Джейла; Монтес, Пабло; Шетти, Прадип; Spillane, Ричард П .; Задок, Эрез (июнь 2011 г.). «Не трэш: как кэшировать хеш на флэш-памяти» (PDF). Материалы 3-й конференции USENIX по актуальным вопросам хранения и файловых систем (HotStorage'11). Получено 21 июля 2012.
  5. ^ Бендер, Майкл А .; Фарач-Колтон, Мартин; Джонсон, Роб; Кранер, Рассел; Kuszmaul, Bradley C .; Медедович, Джейла; Монтес, Пабло; Шетти, Прадип; Spillane, Ричард П .; Садок, Эрез (27–31 августа 2012 г.). «Не трэш: как кэшировать хеш на флэш-памяти» (PDF). Труды эндаумента VLDB. 5 (11): 1627–1637. arXiv:1208.0290. Bibcode:2012arXiv1208.0290B. Дои:10.14778/2350229.2350275. S2CID  47180056.
  6. ^ а б Панди, Прашант; Бендер, Майкл А .; Джонсон, Роб; Патро, Роб (май 2017). «Счетный фильтр общего назначения: учитывает каждый бит». Материалы Международной конференции ACM по управлению данными 2017 г. (SIGMOD '17). Получено 2 декабря 2020.
  7. ^ Кнут, Дональд (1973). Искусство программирования: поиск и сортировка, том 3. Раздел 6.4, упражнение 13: Эддисон Уэсли.CS1 maint: location (связь)
  8. ^ Чанг, Фэй; и другие. (2006). «Bigtable: распределенная система хранения структурированных данных» (PDF). OSDI '06: Материалы 7-го симпозиума USENIX по разработке и внедрению операционных систем: 15. Получено 21 июля 2012.
  9. ^ О'Нил, Патрик; и другие. (1996). "Дерево слияния с лог-структурой (LSM-дерево)". Acta Informatica. 33 (4): 351–385. Дои:10.1007 / s002360050048. S2CID  12627452.
  10. ^ Спиллейн, Ричард (май 2012 г.). «Эффективное, масштабируемое и универсальное управление приложениями и системными транзакциями для уровней прямого хранения» (PDF). Получено 21 июля 2012. Цитировать журнал требует | журнал = (помощь)

внешняя ссылка