Quotient filter — различия между версиями
Kurkin (обсуждение | вклад) |
Kurkin (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
− | [[Файл:filter.png| | + | [[Файл:filter.png|500px|thumb|right|Фильтр используется для ускорения ответов в хранилище ключ-значение. Пары ключ-значение содержатся в хранилище с медленным доступом. Фильтр отфильтровывает ненужные запросы в хранилище (запрос ключа которого точно нет в хранилище), что ускоряет его работу вцелом, но увеличевает потребление памяти]] |
'''Quotient filter''' {{---}} вероятностная структура данных, позволяющая проверить принадлежность элемента множеству. При этом существует возможность получить ложноположительное срабатывание (элемента в множестве нет, но структура данных сообщает, что он есть), но не ложноотрицательное (элемент в множестве есть, но структура данных сообщает, что его нет). | '''Quotient filter''' {{---}} вероятностная структура данных, позволяющая проверить принадлежность элемента множеству. При этом существует возможность получить ложноположительное срабатывание (элемента в множестве нет, но структура данных сообщает, что он есть), но не ложноотрицательное (элемент в множестве есть, но структура данных сообщает, что его нет). | ||
Строка 9: | Строка 9: | ||
Фильтр представляет собой [[:Хеш-таблица|хеш-таблицу]], в которой харанится часть ключа и <tex>3</tex> бита дополнительной информации. Они используются для разрешения ситуации, когда хеш различных ключей указывает на одну ячейку в хеш-таблице. В quotient filter хеш-функция возвращает <tex>p</tex> битовый хеш, последние r бит которого называются '''остатком''' (англ. ''remainder''), а <tex>q = p - r</tex> старших бит называются '''частным''' (англ. ''quotient''), отсюда название структуры Quotient filter<ref>Knuth, Donald (1973). The Art of Computer Programming:Searching and Sorting, volume 3. Section 6.4, exercise 13: Addison Wesley</ref>. Размер хеш-таблицы составляет <tex>2^q</tex>. | Фильтр представляет собой [[:Хеш-таблица|хеш-таблицу]], в которой харанится часть ключа и <tex>3</tex> бита дополнительной информации. Они используются для разрешения ситуации, когда хеш различных ключей указывает на одну ячейку в хеш-таблице. В quotient filter хеш-функция возвращает <tex>p</tex> битовый хеш, последние r бит которого называются '''остатком''' (англ. ''remainder''), а <tex>q = p - r</tex> старших бит называются '''частным''' (англ. ''quotient''), отсюда название структуры Quotient filter<ref>Knuth, Donald (1973). The Art of Computer Programming:Searching and Sorting, volume 3. Section 6.4, exercise 13: Addison Wesley</ref>. Размер хеш-таблицы составляет <tex>2^q</tex>. | ||
− | Пусть у нас есть ключ <tex>K</tex>, его хеш обозначим <tex> | + | Пусть у нас есть ключ <tex>K</tex>, его хеш обозначим <tex>h(K)</tex>, остаток <tex>H_r</tex> и частное <tex>H_q</tex>. Попробуем поместить остаток в хеш-таблицу в ячейку <tex>H_q</tex>, называемую канонической. Возможно, ячейка уже занята, так как существует шанс полных коллизий (остаток и частное разных ключей совпадают) или частичных коллизий (частное разных ключей совпадают). Когда каноническая ячейка занята, помещаем остаток в какую-то ячейку справа. Этот способ решения колизий схож с [[:Разрешение_коллизий|линейным методом разрешения колизий]]. |
Последовательность ячеек, имеющих одинаковые частные называется '''пробегом''' (англ. ''run''). Возможно, что начало пробега не занимает канонический слот, если он уже занят каким-то другим пробегом. | Последовательность ячеек, имеющих одинаковые частные называется '''пробегом''' (англ. ''run''). Возможно, что начало пробега не занимает канонический слот, если он уже занят каким-то другим пробегом. | ||
− | Пробег, у которого первый элемент занимает каноническую ячейку, является началом кластера. '''Кластер''' | + | Пробег, у которого первый элемент занимает каноническую ячейку, является началом кластера. '''Кластер''' {{---}} объединение последовательных пробегов, концом кластера является пустая ячейка или начало другого кластера. |
Три дополнительных бита имеют следующие функции: | Три дополнительных бита имеют следующие функции: | ||
Строка 20: | Строка 20: | ||
* бит сдвига {{---}} равен единице, если пробег сдвинут относительно канонического слота. | * бит сдвига {{---}} равен единице, если пробег сдвинут относительно канонического слота. | ||
+ | [[Файл:Quotient Filter.png|500px|thumb|right|Пример последовательной вставки элементов <tex> b, f, e, c, d, a</tex>]] | ||
{| class="wikitable" border=1 | {| class="wikitable" border=1 | ||
|+ | |+ | ||
Строка 31: | Строка 32: | ||
|0||1||0||style="text-align:left;"|Не используется. | |0||1||0||style="text-align:left;"|Не используется. | ||
|-align="center" bgcolor=#FFFFFF | |-align="center" bgcolor=#FFFFFF | ||
− | |0||1||1||style="text-align:left;"|Ячейка содержит элемент пробега(не первый), сдвинутого относительно канонического слота. | + | |0||1||1||style="text-align:left;"|Ячейка содержит элемент пробега (не первый), сдвинутого относительно канонического слота. |
|-align="center" bgcolor=#FFFFFF | |-align="center" bgcolor=#FFFFFF | ||
|1||0||0||style="text-align:left;"|Ячейка содержит первый элемет пробега в его каноническом слоте. | |1||0||0||style="text-align:left;"|Ячейка содержит первый элемет пробега в его каноническом слоте. | ||
Строка 39: | Строка 40: | ||
|1||1||0||style="text-align:left;"|Не используется. | |1||1||0||style="text-align:left;"|Не используется. | ||
|-align="center" bgcolor=#FFFFFF | |-align="center" bgcolor=#FFFFFF | ||
− | |1||1||1||style="text-align:left;"|Ячейка содержит элемент пробега(не первый), сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо. | + | |1||1||1||style="text-align:left;"|Ячейка содержит элемент пробега (не первый), сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо. |
|} | |} | ||
=== Поиск === | === Поиск === | ||
− | |||
Пусть мы ищем ключ <tex>K</tex>. Смотрим в его каноническую ячейку <tex>H_q</tex>. Если бит занятости не единица, то элемент точно не содержится в множестве. | Пусть мы ищем ключ <tex>K</tex>. Смотрим в его каноническую ячейку <tex>H_q</tex>. Если бит занятости не единица, то элемент точно не содержится в множестве. | ||
Строка 71: | Строка 71: | ||
<references /> | <references /> | ||
− | == Источники == | + | == Источники информации == |
* [http://en.wikipedia.org/wiki/Quotient_filter Wikipedia — Quotient filter] | * [http://en.wikipedia.org/wiki/Quotient_filter Wikipedia — Quotient filter] |
Версия 23:07, 6 июня 2015
Quotient filter — вероятностная структура данных, позволяющая проверить принадлежность элемента множеству. При этом существует возможность получить ложноположительное срабатывание (элемента в множестве нет, но структура данных сообщает, что он есть), но не ложноотрицательное (элемент в множестве есть, но структура данных сообщает, что его нет).
Существует связь между размером хранилища и шансом ложноположительного срабатывания. Поддерживаются операции добавления нового элемента в множество. С увеличением размера хранимого множества повышается вероятность ложного срабатывания. Структуру разработал Michael Bender в 2011 году[1] как замена фильтра Блума. Фильтр используется для ускорения ответов в хранилище ключ-значение.
Содержание
Описание структуры данных
Фильтр представляет собой хеш-таблицу, в которой харанится часть ключа и бита дополнительной информации. Они используются для разрешения ситуации, когда хеш различных ключей указывает на одну ячейку в хеш-таблице. В quotient filter хеш-функция возвращает битовый хеш, последние r бит которого называются остатком (англ. remainder), а старших бит называются частным (англ. quotient), отсюда название структуры Quotient filter[2]. Размер хеш-таблицы составляет .
Пусть у нас есть ключ линейным методом разрешения колизий.
, его хеш обозначим , остаток и частное . Попробуем поместить остаток в хеш-таблицу в ячейку , называемую канонической. Возможно, ячейка уже занята, так как существует шанс полных коллизий (остаток и частное разных ключей совпадают) или частичных коллизий (частное разных ключей совпадают). Когда каноническая ячейка занята, помещаем остаток в какую-то ячейку справа. Этот способ решения колизий схож сПоследовательность ячеек, имеющих одинаковые частные называется пробегом (англ. run). Возможно, что начало пробега не занимает канонический слот, если он уже занят каким-то другим пробегом.
Пробег, у которого первый элемент занимает каноническую ячейку, является началом кластера. Кластер — объединение последовательных пробегов, концом кластера является пустая ячейка или начало другого кластера.
Три дополнительных бита имеют следующие функции:
- бит занятости — равен единице, если ячейка является канонической для некого ключа в фильтре, сохраненого необязательно в этой ячейке,
- бит продолжения — равен единице, если ячейка занята, но не первым элементов пробеге,
- бит сдвига — равен единице, если пробег сдвинут относительно канонического слота.
Бит занятости | Бит Продолжения | Бит сдвига | Описание |
---|---|---|---|
0 | 0 | 0 | Пустая ячейка. |
0 | 0 | 1 | Ячейка содержит начало пробега, сдвинутого относительно канонического слота. |
0 | 1 | 0 | Не используется. |
0 | 1 | 1 | Ячейка содержит элемент пробега (не первый), сдвинутого относительно канонического слота. |
1 | 0 | 0 | Ячейка содержит первый элемет пробега в его каноническом слоте. |
1 | 0 | 1 | Ячейка содержит первый элемет пробега, сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо. |
1 | 1 | 0 | Не используется. |
1 | 1 | 1 | Ячейка содержит элемент пробега (не первый), сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо. |
Поиск
Пусть мы ищем ключ
. Смотрим в его каноническую ячейку . Если бит занятости не единица, то элемент точно не содержится в множестве. Если бит занятости единица, то нам нужно найти пробег для . Так как начало нужного пробега может быть сдвинуто, найдем начало кластера. Идем влево от ячейки и ищем первую с битом сдвига равным нулю, эта ячейка и будет началом кластера. Пока мы идем влево от будем поддерживать счетчик, который бедет показывать сколько пробегов нам нужно будет пропустить от начала кластера. Каждая ячейка с битом занятости равным единице увеличивает счетчик на . После того как мы нашли начало кластера, пойдем от него влево, каждая ячейка с битом продолжения равным нулю говорит о завершении пробега, когда счетчик станет равным нулю мы найдем нужный нам пробег для . Если в этом пробеге содержится , то , вероятно, содержится в множестве, иначе точно не содержится в множестве.Вставка
Аналогично с поиском: найдем позицию для
, сдвигаем на одну позицию влево все эллементы кластера, начиная с выбранного, обновляем дополнительные биты.- Сдвиг не влияет на бит занятости. Выставляем бит занятости в ячейке в единицу.
- Если мы вставляем в начало пробега, следовательно предыдущий элемент пробега стал вторым, у него нужно выставить бит продолжения.
- Мы выставляем бит сдвига в единицу для каждой ячейки, что мы сдвинули.
Преимущества
- Последовательное расположение данных. Можно загружать только кластер, уменьшая количество кеш промахов.
- Простое увеличение или уменьшение хеш-таблицы, достаточно перенести один бит из остатка в частное или наоборот.
- Простое слияние двух фильтров.
См. также
Примечания
- ↑ Bender, Michael A.; Farach-Colton, Martin; Johnson, Rob; Kuszmaul, Bradley C.; Medjedovic, Dzejla; Montes, Pablo; Shetty, Pradeep; Spillane, Richard P.; Zadok, Erez (June 2011)."Don't thrash: how to cache your hash on flash" (PDF)
- ↑ Knuth, Donald (1973). The Art of Computer Programming:Searching and Sorting, volume 3. Section 6.4, exercise 13: Addison Wesley