Изменения
→Поиск
'''Quotient filter''' {{---}} вероятностная структура данных, позволяющая проверить принадлежность элемента множеству. При этом существует возможность получить ложноположительное срабатывание (элемента в множестве нет, но структура данных сообщает, что он есть), но не ложноотрицательное(элемент в множестве есть, но структура данных сообщает, что его нет)[[Фильтр_Блума#Определение|вероятностное множество]].
Существует связь между размером хранилища и шансом ложноположительного срабатывания. Поддерживаются операции добавления нового элемента в множество. С увеличением размера хранимого множества повышается вероятность ложного срабатывания.
Структуру разработал Michael Bender в 2011 году<ref>Bender, Michael A.; Farach-Colton, Martin; Johnson, Rob; Kuszmaul, Bradley C.; Medjedovic, Dzejla; Montes, Pablo; Shetty, Pradeep; Spillane, Richard P.; Zadok, Erez (June 2011).[http://vldb.org/pvldb/vol5/p1627_michaelabender_vldb2012.pdf "Don't thrash: how to cache your hash on flash" (PDF)]</ref> как замена [[:Фильтр_Блума|фильтра Блума]].Фильтр используется для ускорения ответов в хранилище ключ-значение.
==Описание структуры данных==
[[Файл:filter.png|400px|thumb|right|Фильтр используется для ускорения ответов в хранилище ключ-значение. Пары ключ-значение содержатся в хранилище с медленным доступом. Фильтр отфильтровывает ненужные запросы в хранилище (запрос ключа которого точно нет в хранилище), что ускоряет его работу вцелом, но увеличевает потребление памяти]]
Пусть у нас есть ключ <tex>DK</tex>, его хеш обозначим <tex>Dhh(K)</tex>, остаток <tex>Drh_r</tex> и частное <tex>Dqh_q</tex>. Попробуем поместить остаток в хеш -таблицу в ячейку с индексом <tex>Dqh_q</tex>, называемую канонической. Возможно, ячейка уже занята, так как существует шанс полных коллизий (остаток и частное разных ключей совпадают) или частичных коллизий (частное разных ключей совпадают). При полной коллизии мы получим ложноположительное срабатывание, но при частичной коллизии, с помощью дополнительных битов это избегается. Когда каноническая ячейка занята, помещаем остаток в какую-то ячейку справа. Этот способ решения колизий схож с [[:Разрешение_коллизий|линейным методом разрешения колизий]].
Последовательность ячеек, имеющих одинаковые частные называется '''пробегом ''' (англ. ''run''). Возможно, что начало пробега не занимает канонический слот, если он уже занят каким-то другим пробегом.
Пробег, у которого первый элемент занимает каноническую ячейку, является началом кластера. Кластер (англ. ''cluster'') {{---}} объединение последовательных пробегов, концом кластера является пустая ячейка или начало другого кластера.
Три дополнительных бита имеют следующие функции:
[[Файл:Quotient Filter.png|500px|thumb|right|Пример последовательной вставки элементов <tex> b, f, e, c, d, a</tex>]]
{| class="wikitable" border=1
|+
|0||1||0||style="text-align:left;"|Не используется.
|-align="center" bgcolor=#FFFFFF
|0||1||1||style="text-align:left;"|Ячейка содержит элемент пробега(не первый), сдвинутого относительно канонического слота.
|-align="center" bgcolor=#FFFFFF
|1||0||0||style="text-align:left;"|Ячейка содержит первый элемет пробега в его каноническом слоте.
|1||1||0||style="text-align:left;"|Не используется.
|-align="center" bgcolor=#FFFFFF
|1||1||1||style="text-align:left;"|Ячейка содержит элемент пробега(не первый), сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо.
|}
=== Поиск ===
Пусть мы ищем ключ <tex>DK</tex>. Смотрим в его каноническую ячейку с индексом <tex>h_q</tex>, это каноническая ячейка для частного <tex>Dqh_q</tex>. Если в этой ячейке бит занятости не единица, то элемент точно не содержится в множестве.Если бит занятости единица, то нам нужно найти пробег для <tex>Dqh_q</tex>. Так как начало нужного пробега может быть сдвинуто, найдем начало кластера. Идем влево от ячейки с индексом <tex>Dqh_q</tex> и ищем первую с битом сдвига равным нулю, эта ячейка и будет началом кластера. Пока мы идем влево от ячейки с индексом <tex>Dqh_q</tex> будем поддерживать счетчик, который бедет показывать сколько пробегов нам нужно будет пропустить от начала кластера. Каждая ячейка с битом занятости равным единице увеличивает счетчик на <tex>1</tex>. После того как мы нашли начало кластера, пойдем от него влевовправо, каждая ячейка с битом продолжения равным нулю говорит о завершении пробега, когда счетчик станет равным нулю мы найдем нужный нам пробег для частного <tex>Dqh_q</tex>. Если в этом пробеге содержится <tex>Drh_r</tex>, то <tex>DK</tex> ,вероятно, содержится в множестве, иначе <tex>DK</tex> точно не содержится в множестве.
=== Вставка ===
Аналогично с поиском: найдем позицию для <tex>Drh_r</tex>, сдвигаем на одну позицию влево все эллементы кластера, начиная с выбранного, обновляем дополнительные биты.
* Сдвиг не влияет на бит занятости. Выставляем бит занятости в ячейке <tex>Dqh_q</tex> в единицу.* Если мы вставляем <tex>Drh_r</tex> в начало пробега, следовательно предыдущий элемент пробега стал вторым, у него нужно выставить бит продолжения.
* Мы выставляем бит сдвига в единицу для каждой ячейки, что мы сдвинули.
== Преимущества ==
* Последовательное расположение данных. Можно загружать только <tex>1 </tex> кластер, уменьшая количество кеш промахов.* Простое увеличение или уменьшение хеш -таблицы, достаточно перенести один бит из остатка в частное или наоборот.
* Простое слияние двух фильтров.
==См. Такжетакже==
*[[:Идеальное_хеширование|Идеальное хеширование]]
<references />
== Источники информации ==
* [http://en.wikipedia.org/wiki/Quotient_filter Wikipedia — Quotient filter]