Jump to content

Расширяемое хеширование

Расширяемое хеширование — это тип хеш- системы, которая рассматривает хэш как битовую строку и использует дерево для поиска в сегменте. [1] Из-за иерархической природы системы повторное хеширование является инкрементной операцией (выполняется по одному сегменту за раз, по мере необходимости). Это означает, что рост таблицы меньше влияет на чувствительные ко времени приложения, чем стандартное полное перехеширование таблицы.

Расширяемое хеширование было описано Рональдом Феджином в 1979 году. Практически все современные файловые системы используют либо расширяемое хеширование, либо B-деревья . В частности, Global File System , ZFS и SpadFS используют расширяемое хеширование. [2]

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

Ключи, которые будут использоваться:

Предположим, что в этом конкретном примере размер сегмента равен 1. Первые два вставляемых ключа, k 1 и k 2 , можно отличить по старшему биту , и они будут вставлены в таблицу следующим образом:

Теперь, если бы k 3 было хэшировано с таблицей, было бы недостаточно различать все три ключа по одному биту (потому что и k 3 , и k 1 имеют 1 в качестве крайнего левого бита). Кроме того, поскольку размер сегмента равен единице, таблица может переполниться. Поскольку сравнение первых двух старших битов дает каждому ключу уникальное местоположение, размер каталога удваивается следующим образом:

Итак, теперь k 1 и k 3 имеют уникальное местоположение, отличающееся первыми двумя крайними левыми битами. Поскольку k 2 находится в верхней половине таблицы, на него указывают как 00, так и 01, поскольку нет другого ключа для сравнения, начинающегося с 0.

Приведенный выше пример взят из Fagin et al. (1979) .

Дополнительная информация

[ редактировать ]

Теперь необходимо вставить k 4 , первые два бита которого равны 01..(1110), и при использовании глубины каталога в 2 бита это сопоставляется с 01 с сегментом A. Блок A заполнен (максимальный размер 1). ), поэтому его необходимо разделить; поскольку на сегмент A имеется более одного указателя, нет необходимости увеличивать размер каталога.

Необходима информация о:

  1. Размер ключа, который отображает каталог (глобальная глубина), и
  2. Размер ключа, который ранее сопоставил сегмент (локальная глубина).

Чтобы различать два случая действия:

  1. Удвоение каталога при заполнении корзины
  2. Создание новой корзины и перераспределение записей между старой и новой корзиной.

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

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

Таким образом, если глобальная глубина = локальная глубина = 0, то 2 0 = 1, поэтому начальный каталог содержит один указатель на одну корзину.

Вернёмся к двум случаям действий; если ведро полное:

  1. Если локальная глубина равна глобальной глубине, то существует только один указатель на сегмент, и нет других указателей каталогов, которые могли бы сопоставиться с сегментом, поэтому каталог необходимо удвоить.
  2. Если локальная глубина меньше глобальной глубины, то существует более одного указателя из каталога на сегмент, и сегмент можно разделить.

Ключ 01 указывает на сегмент A, а локальная глубина сегмента A, равная 1, меньше глобальной глубины каталога, равной 2, что означает, что ключи, хешированные для сегмента A, использовали только 1-битный префикс (т. е. 0), и сегмент должен иметь свой содержимое разделяется с помощью ключей длиной 1 + 1 = 2 бита; в общем, для любой локальной глубины d, где d меньше D, глобальная глубина, а затем d должна быть увеличена после разделения сегмента, а новый d используется как количество битов ключа каждой записи для перераспределения записей прежней ведро в новые ведра.

Сейчас,

пробуется еще раз, с 2 битами 01.., и теперь ключ 01 указывает на новую корзину, но все еще есть в нем ( и тоже начинается с 01).

Если был 000110, с ключом 00 проблем не было бы, потому что остался бы в новом ведре A', а ведро D было бы пустым.

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

Таким образом, сегмент D необходимо разделить, но проверка его локальной глубины, равной 2, аналогична проверке глобальной глубины, равной 2, поэтому каталог необходимо разделить еще раз, чтобы хранить ключи с достаточной детализацией, например 3 бита.

  1. Ведро D необходимо разделить, так как оно заполнено.
  2. Поскольку локальная глубина D = глобальной глубине, каталог должен удвоиться, чтобы увеличить детализацию ключей.
  3. Глобальная глубина увеличилась после разделения каталога на 3.
  4. Новая запись переназначается с глобальной глубиной 3 бита и попадает в D, который имеет локальную глубину 2, которую теперь можно увеличить до 3, а D можно разделить на D' и E.
  5. Содержимое разделенного ведра D, был перекодирован с использованием 3 битов и в итоге оказался в D'.
  6. K4 повторяется и попадает в E, у которого есть свободный слот.

Сейчас, находится в D и пробуется еще раз, с 3 битами 011.., и он указывает на сегмент D, который уже содержит так полно; Локальная глубина D равна 2, но теперь глобальная глубина равна 3 после удвоения каталога, поэтому теперь D можно разделить на D' и E корзины, содержимое D, имеет свой повторная попытка с новой глобальной битовой маской глубины 3 и оказывается в D', затем появляется новая запись повторяется с побитовая маска с использованием нового количества битов глобальной глубины, равного 3, и это дает 011, что теперь указывает на новую корзину E, которая пуста. Итак попадает в ведро E.

Пример реализации

[ редактировать ]

Ниже приведен расширяемый алгоритм хеширования на Python , в котором удалены проблемы ассоциации блока диска/страницы памяти, кэширования и согласованности. Обратите внимание, что проблема существует, если глубина превышает размер целого числа в битах, поскольку тогда удвоение каталога или разделение сегмента не позволит перехешировать записи в разные сегменты.

В коде используются младшие биты , что позволяет более эффективно расширять таблицу, поскольку весь каталог можно скопировать как один блок ( Ramakrishnan & Gehrke (2003) ).

Пример Python

[ редактировать ]
PAGE_SZ = 10

class Page:
    def __init__(self) -> None:
        self.map = []
        self.local_depth = 0

    def full(self) -> bool:
        return len(self.map) >= PAGE_SZ

    def put(self, k, v) -> None:
        for i, (key, value) in enumerate(self.map):
            if key == k:
                del self.map[i]
                break
        self.map.append((k, v))

    def get(self, k):
        for key, value in self.map:
            if key == k:
                return value

    def get_local_high_bit(self):
      return 1 << self.local_depth

class ExtendibleHashing:
    def __init__(self) -> None:
        self.global_depth = 0
        self.directory = [Page()]

    def get_page(self, k):
        h = hash(k)
        return self.directory[h & ((1 << self.global_depth) - 1)]

    def put(self, k, v) -> None:
        p = self.get_page(k)
        full = p.full()
        p.put(k, v)
        if full:
            if p.local_depth == self.global_depth:
                self.directory *= 2
                self.global_depth += 1

            p0 = Page()
            p1 = Page()
            p0.local_depth = p1.local_depth = p.local_depth + 1
            high_bit = p.get_local_high_bit()
            for k2, v2 in p.map:
                h = hash(k2)
                new_p = p1 if h & high_bit else p0
                new_p.put(k2, v2)

            for i in range(hash(k) & (high_bit - 1), len(self.directory), high_bit):
                self.directory[i] = p1 if i & high_bit else p0
         
  
    def get(self, k):
        return self.get_page(k).get(k)

if __name__ == "__main__":
    eh = ExtendibleHashing()
    N = 10088
    l = list(range(N))

    import random
    random.shuffle(l)
    for x in l:
        eh.put(x, x)
    print(l)

    for i in range(N):
        print(eh.get(i))

Примечания

[ редактировать ]
  1. ^ Феджин и др. (1979) .
  2. ^ Микулаш Паточка (2006). Проектирование и реализация файловой системы Spad (PDF) (Диссертация). Архивировано из оригинала (PDF) 15 марта 2016 г. Проверено 27 февраля 2016 г. «Раздел 4.1.6 Расширяемое хеширование: ZFS и GFS» и «Таблица 4.1: Организация каталогов в файловых системах»

См. также

[ редактировать ]
  • Феджин, Р.; Нивергельт, Дж.; Пиппенджер, Н.; Стронг, HR (сентябрь 1979 г.), «Расширяемое хеширование — метод быстрого доступа к динамическим файлам», Транзакции ACM в системах баз данных , 4 (3): 315–344, doi : 10.1145/320083.320092 , S2CID   2723596
  • Рамакришнан, Р.; Герке, Дж. (2003), Системы управления базами данных, 3-е издание: Глава 11, Индексирование на основе хеша , стр. 373–378.
  • Зильбершац, Авраам ; Корт, Генри ; Сударшан, С., Концепции системы баз данных, шестое издание: глава 11.7, Динамическое хеширование
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: fd2eed1e140c9d5841ec5ecb62abaabe__1716984240
URL1:https://arc.ask3.ru/arc/aa/fd/be/fd2eed1e140c9d5841ec5ecb62abaabe.html
Заголовок, (Title) документа по адресу, URL1:
Extendible hashing - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)