Редактирование: Quotient filter

Перейти к: навигация, поиск

Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.

Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия Ваш текст
Строка 1: Строка 1:
'''Quotient filter''' {{---}} [[Фильтр_Блума#Определение|вероятностное множество]].
+
'''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> как замена [[:Фильтр_Блума|фильтра Блума]]. Фильтр используется для ускорения ответов в хранилище ключ-значение. 
+
Структуру разработал Michael Bender в 2011 году как замена [[:Фильтр_Блума|фильтра Блума]].
  
 
==Описание структуры данных==
 
==Описание структуры данных==
[[Файл:filter.png|400px|thumb|right|Фильтр используется для ускорения ответов в хранилище ключ-значение. Пары ключ-значение содержатся в хранилище с медленным доступом. Фильтр отфильтровывает ненужные запросы в хранилище (запрос ключа которого точно нет в хранилище), что ускоряет его работу вцелом, но увеличевает потребление памяти]]
 
  
В quotient filter хеш-функция возвращает <tex>p</tex> битовый хеш, последние <tex>r</tex> бит которого называются '''остатком''' (англ. ''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>3</tex> бита дополнительной информации (удобно хранить в целочисленном типе, используя <tex>3</tex> старших бита под дополнительную информацию, а оставшиеся биты под остаток, накладывает ограничение на размер остатка). Биты дополнительной информации используются для разрешения ситуации, когда частное различных ключей указывает на одну ячейку в хеш-таблице. Размер хеш-таблицы составляет <tex>2^q</tex>, так как есть всего <tex>2^q</tex> разных частных.
+
Фильтр представляет собой [[:Хеш-таблица|хеш-таблицу]], в которой харанится часть ключа и 3 бита дополнительной информации. Они используются для разрешения ситуации, когда хеш различных ключей указывает на одну ячейку в хеш таблице. В <tex>Quotient filter</tex> хеш функция возвращает <tex>p</tex> битовый хеш, последние r бит которого называются остатком, а <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>h(K)</tex>, остаток <tex>h_r</tex> и частное <tex>h_q</tex>. Попробуем поместить остаток в хеш-таблицу в ячейку с индексом <tex>h_q</tex>, называемую канонической. Возможно, ячейка уже занята, так как существует шанс полных коллизий (остаток и частное разных ключей совпадают) или частичных коллизий (частное разных ключей совпадают).
+
Пусть у нас есть ключ <tex>D</tex>, его хеш обозначим <tex>Dh</tex>, остаток <tex>Dr</tex> и частное <tex>Dq</tex>. Попробуем поместить остаток в хеш таблицу в ячейку <tex>Dq</tex>, называемую канонической. Возможно, ячейка уже занята, так как существует шанс полных коллизий (остаток и частное разных ключей совпадают) или частичных коллизий (частное разных ключей совпадают). Когда каноническая ячейка занята, помещаем остаток в какую-то ячейку справа.
При полной коллизии мы получим ложноположительное срабатывание, но при частичной коллизии, с помощью дополнительных битов это избегается. Когда каноническая ячейка занята, помещаем остаток в какую-то ячейку справа. Этот способ решения колизий схож с [[:Разрешение_коллизий|линейным методом разрешения колизий]].  
 
  
Последовательность ячеек, имеющих одинаковые частные называется '''пробегом''' (англ. ''run''). Возможно, что начало пробега не занимает канонический слот, если он уже занят каким-то другим пробегом.
+
Последовательность ячеек, имеющих одинаковые частные называется пробегом (англ. ''run''). Возможно, что начало пробега не занимает канонический слот, если он уже занят каким-то другим пробегом.
  
Пробег, у которого первый элемент занимает каноническую ячейку, является началом кластера. Кластер {{---}} объединение последовательных пробегов, концом кластера является пустая ячейка или начало другого кластера.
+
Пробег, у которого первый элемент занимает каноническую ячейку, является началом кластера. Кластер (англ. ''cluster'') {{---}} объединение последовательных пробегов, концом кластера является пустая ячейка или начало другого кластера.
  
 
Три дополнительных бита имеют следующие функции:
 
Три дополнительных бита имеют следующие функции:
* бит занятости {{---}} равен единице, если ячейка является канонической для некого ключа в фильтре, сохраненого необязательно в этой ячейке,
+
# бит занятости {{---}} равен единице, если ячейка является канонической для некого ключа в фильтре, сохраненого необязательно в этой ячейке.
* бит продолжения {{---}} равен единице, если ячейка занята, но не первым элементов пробеге,
+
# бит продолжения {{---}} равен единице, если ячейка занята, но не первым элементов пробеге.
* бит сдвига {{---}} равен единице, если пробег сдвинут относительно канонического слота.
+
# бит сдвига {{---}} равен единице, если пробег сдвинут относительно канонического слота.
  
[[Файл:Quotient Filter.png|500px|thumb|right|Пример последовательной вставки элементов <tex> b, f, e, c, d, a</tex>]]
+
 
{| class="wikitable" border=1
+
Возможные состояния:
|+
+
0 0 0 : Пустая ячейка.  
|-align="center" bgcolor=#EEEEFF
+
0 0 1 : Ячейка содержит начало пробега, сдвинутого относительно канонического слота.  
! Бит занятости || Бит Продолжения || Бит сдвига || Описание
+
0 1 0 : не используется.  
|-align="center" bgcolor=#FFFFFF
+
0 1 1 : Ячейка содержит элемент пробега(не первый), сдвинутого относительно канонического слота.  
|0||0||0||style="text-align:left;"|Пустая ячейка.
+
1 0 0 : Ячейка содержит первый элемет пробега в его каноническом слоте.  
|-align="center" bgcolor=#FFFFFF
+
1 0 1 : Ячейка содержит первый элемет пробега, сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо.  
|0||0||1||style="text-align:left;"|Ячейка содержит начало пробега, сдвинутого относительно канонического слота.
+
1 1 0 : не используется.  
|-align="center" bgcolor=#FFFFFF
+
1 1 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;"|Ячейка содержит первый элемет пробега в его каноническом слоте.
 
|-align="center" bgcolor=#FFFFFF
 
|1||0||1||style="text-align:left;"|Ячейка содержит первый элемет пробега, сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо.
 
|-align="center" bgcolor=#FFFFFF
 
|1||1||0||style="text-align:left;"|Не используется.
 
|-align="center" bgcolor=#FFFFFF
 
|1||1||1||style="text-align:left;"|Ячейка содержит элемент пробега (не первый), сдвинутого относительно канонического слота. Ячейка является канонической, для существующего пробега сдвинутого вправо.
 
|}
 
  
 
=== Поиск ===
 
=== Поиск ===
  
Пусть мы ищем ключ <tex>K</tex>. Смотрим в ячейку с индексом <tex>h_q</tex>, это каноническая ячейка для частного <tex>h_q</tex>. Если в этой ячейке бит занятости не единица, то элемент точно не содержится в множестве.
+
Пусть мы ищем ключ <tex>D</tex>. Смотрим в его каноническую ячейку <tex>Dq</tex>. Если бит занятости не единица, то элемент точно не содержится в множестве.
Если бит занятости единица, то нам нужно найти пробег для <tex>h_q</tex>. Так как начало нужного пробега может быть сдвинуто, найдем начало кластера. Идем влево от ячейки с индексом <tex>h_q</tex> и ищем первую с битом сдвига равным нулю, эта ячейка и будет началом кластера. Пока мы идем влево от ячейки с индексом <tex>h_q</tex> будем поддерживать счетчик, который бедет показывать сколько пробегов нам нужно будет пропустить от начала кластера. Каждая ячейка с битом занятости равным единице увеличивает счетчик на <tex>1</tex>. После того как мы нашли начало кластера, пойдем от него вправо, каждая ячейка с битом продолжения равным нулю говорит о завершении пробега, когда счетчик станет равным нулю мы найдем нужный нам пробег для частного <tex>h_q</tex>. Если в этом пробеге содержится <tex>h_r</tex>, то <tex>K</tex>, вероятно, содержится в множестве, иначе <tex>K</tex> точно не содержится в множестве.
+
Если бит занятости единица, то нам нужно найти пробег для <tex>Dq</tex>. Так как начало нужного пробега может быть сдвинуто, найдем начало кластера. Идем влево от ячейки <tex>Dq</tex> и ищем первую с битом сдвига равным нулю, эта ячейка и будет началом кластера. Пока мы идем влево от <tex>Dq</tex> будем поддерживать счетчик, который бедет показывать сколько пробегов нам нужно будет пропустить от начала кластера. Каждая ячейка с битом занятости равным единице увеличивает счетчик на <tex>1</tex>. После того как мы нашли начало кластера, пойдем от него влево, каждая ячейка с битом продолжения равным нулю говорит о завершении пробега, когда счетчик станет равным нулю мы найдем нужный нам пробег для <tex>Dq</tex>. Если в этом пробеге содержится <tex>Dr</tex>, то <tex>D</tex> ,вероятно, содержится в множестве, иначе <tex>D</tex> точно не содержится в множестве.
  
 
=== Вставка ===
 
=== Вставка ===
  
Аналогично с поиском: найдем позицию для <tex>h_r</tex>, сдвигаем на одну позицию влево все эллементы кластера, начиная с выбранного, обновляем дополнительные биты.  
+
Аналогично с поиском: найдем позицию для <tex>Dr</tex>, сдвигаем на одну позицию влево все эллементы кластера, начиная с выбранного, обновляем дополнительные биты.  
  
* Сдвиг не влияет на бит занятости. Выставляем бит занятости в ячейке <tex>h_q</tex> в единицу.
+
* Сдвиг не влияет на бит занятости. Выставляем бит занятости в ячейке <tex>Dq</tex> в единицу.
* Если мы вставляем <tex>h_r</tex> в начало пробега, следовательно предыдущий элемент пробега стал вторым, у него нужно выставить бит продолжения.
+
* Если мы вставляем <tex>Dr</tex> в начало пробега, следовательно предыдущий элемент пробега стал вторым, у него нужно выставить бит продолжения.
 
* Мы выставляем бит сдвига в единицу для каждой ячейки, что мы сдвинули.
 
* Мы выставляем бит сдвига в единицу для каждой ячейки, что мы сдвинули.
 +
  
 
== Преимущества ==
 
== Преимущества ==
  
* Последовательное расположение данных. Можно загружать только <tex>1</tex> кластер, уменьшая количество кеш промахов.
+
* Последовательное расположение данных. Можно загружать только 1 кластер, уменьшая количество кеш промахов.
* Простое увеличение или уменьшение хеш-таблицы, достаточно перенести один бит из остатка в частное или наоборот.
+
* Простое увеличение или уменьшение хеш таблицы, достаточно перенести один бит из остатка в частное или наоборот.
 
* Простое слияние двух фильтров.
 
* Простое слияние двух фильтров.
  
==См. также==
+
==См. Также==
  
 
*[[:Идеальное_хеширование|Идеальное хеширование]]
 
*[[:Идеальное_хеширование|Идеальное хеширование]]
Строка 72: Строка 59:
 
<references />
 
<references />
  
== Источники информации ==
+
== Источники ==
  
 
* [http://en.wikipedia.org/wiki/Quotient_filter Wikipedia — Quotient filter]
 
* [http://en.wikipedia.org/wiki/Quotient_filter Wikipedia — Quotient filter]

Пожалуйста, учтите, что любой ваш вклад в проект «Викиконспекты» может быть отредактирован или удалён другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см. Викиконспекты:Авторские права). НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!

Чтобы изменить эту страницу, пожалуйста, ответьте на приведённый ниже вопрос (подробнее):

Отменить | Справка по редактированию (в новом окне)

Шаблон, используемый на этой странице: