익스텐더블 해싱

Extendible hashing

Extendable 해싱은 해시를 비트 문자열로 처리하고 버킷 조회 시 트라이어를 사용하는 해시 시스템의 일종이다.[1]시스템의 계층적 특성 때문에 재해싱은 증분 연산(필요에 따라 버킷을 한 번에 하나씩 수행)이다.즉, 시간에 민감한 애플리케이션은 표준 전체 테이블 재시도에 비해 테이블 증가의 영향을 덜 받는다는 것을 의미한다.

확장 가능한 해싱은 1979년 로널드 파긴에 의해 설명되었다.사실상 모든 최신 파일 시스템은 확장 가능한 해싱 또는 B-tree를 사용한다.특히 Global File System, ZFS 및 SpadFS 파일 시스템은 확장 가능한 해싱을 사용한다.[2]

해시 함수 h ( )이(가) 비트 문자열을 반환한다고 가정하십시오.각 문자열의 첫 번째 i비트는 "디렉토리"(해시 테이블)에서 그것들이 어디로 갈지 알아내는 인덱스로 사용될 것이다.또한 표에 있는 모든 항목의 색인이 고유할 정도로 나는 가장 작은 숫자다.

사용할 키:

이 특정 예제의 경우 버킷 크기가 1이라고 가정해 봅시다.처음 삽입되는 두 개의 키(k와1 k2)는 가장 중요한 비트로 구별할 수 있으며 다음과 같이 표에 삽입된다.

Extendible hashing 1.svg

이제, 만약3 k를 테이블로 해시한다면, 세 개의 키를 모두 1비트(k와 k 모두 1을 그들의 가장 왼쪽3 비트로1 가지고 있기 때문에)로 구별하기에는 충분하지 않을 것이다.또한, 버킷 크기가 하나이기 때문에 테이블이 넘칠 것이다.처음 두 개의 가장 중요한 비트를 비교하면 각 키에 고유한 위치를 제공할 수 있기 때문에 디렉토리 크기는 다음과 같이 두 배가 된다.

Extendible hashing 2.svg

그래서 이제 k와1 k는3 처음 두 개의 왼쪽 비트로 구별되는 독특한 위치를 갖게 되었다.k는2 테이블의 위쪽 절반에 있기 때문에 0으로 시작하는 그것과 비교할 다른 키가 없기 때문에 00와 01 모두 그것을 가리킨다.

위의 예는 파긴 연구진(1979)에서 나온 것이다.

추가상세부

이제 k를4 삽입해야 하는데, 처음 두 비트는 01로 되어 있다.(1110), 그리고 디렉토리의 2비트 깊이를 사용하여 01에서 버킷 A로 매핑한다.버킷 A가 가득 찼으므로(최대 크기 1) 분할해야 하며, 버킷 A에 대한 포인터가 두 개 이상 있으므로 디렉토리 크기를 늘릴 필요가 없다.

필요한 것은 다음에 대한 정보다.

  1. 디렉토리를 매핑하는 키 크기(전역 깊이)
  2. 버킷을 이전에 매핑한 키 크기(로컬 깊이)

두 가지 조치 사례를 구별하기 위해:

  1. 버킷이 가득 찰 때 디렉터리 배가
  2. 새 버킷 생성 및 이전 버킷과 새 버킷 간에 항목 재분배

확장 가능한 해시 구조의 초기 사례를 살펴보면, 각 디렉토리 항목이 하나의 버킷을 가리킬 경우, 로컬 깊이는 글로벌 깊이와 같아야 한다.

디렉터리 항목 수는 2개global depth, 초기 버킷 수는 2개다local depth.

따라서 전역 깊이가 로컬 깊이 = 0이면 20 = 1이므로 하나의 포인터로 된 초기 디렉터리가 하나의 버킷에 표시된다.

버킷이 가득 찬 경우 다음 두 작업 사례로 돌아가십시오.

  1. 로컬 깊이가 글로벌 깊이와 같을 경우 버킷에 포인터가 하나만 있고 버킷에 매핑할 수 있는 다른 디렉터리 포인터가 없으므로 디렉터리를 두 배로 늘려야 한다.
  2. 로컬 깊이가 글로벌 깊이보다 작으면 디렉터리에서 버킷으로 가는 포인터가 두 개 이상 존재하며 버킷을 분할할 수 있다.
Extendible hashing 3.svg

키 01은 버킷 A를 가리키고 버킷 A의 로컬 깊이 1은 디렉터리의 전역 깊이 2보다 작으므로 버킷 A로 해싱된 키는 1비트 접두사(즉 0)만 사용했으며 버킷의 콘텐츠는 키 1 + 1 = 2비트를 사용하여 분할해야 한다. 일반적으로 d가 글로벌 깊이 D보다 작은 모든 로컬 깊이 d를 대상으로 한다.d는 버킷 분할 후 증가되어야 하며, 이전 버킷의 항목을 새 버킷으로 재배포하기 위해 각 항목 키의 비트 수로 사용되는 새로운 d.

Extendible hashing 4.svg

지금

2비트 01..로 다시 시도되며, 이제 키 은 새 버킷을 가리키지만, 여전히 2 }}개가 들어 있으며(( )= 로 시작됨).

}}개가 키 00과 함께 000110이었다면, 2{\}}개는 새 버킷 A'에 남아 있었을 것이고, 버킷 D는 비어 있었을 것이기 때문에 문제가 없었을 것이다.

(이것은 버킷의 크기가 1보다 크고 새로 분할된 버킷이 넘치지 않는 한 모든 항목이 한 버킷에 다시 연결되지 않는 한, 지금까지 가장 가능성이 높은 경우였을 것이다.그러나 심층정보의 역할을 강조하기 위해서 그 예는 끝까지 논리적으로 추진될 것이다.)

따라서 버킷 D는 분할해야 하지만, 2인 로컬 깊이 확인은 글로벌 깊이인 2와 동일하므로, 충분한 세부사항(예: 3비트)의 키를 보유하기 위해서는 디렉토리를 다시 분할해야 한다.

Extendible hashing 5.svg
  1. 버킷 D는 꽉 차서 분리해야 한다.
  2. D의 로컬 깊이 = 글로벌 깊이로서, 키의 비트 디테일을 증가시키려면 디렉토리가 두 배가 되어야 한다.
  3. 디렉토리가 3으로 분할된 후 전역 깊이가 증가함
  4. 새로운 엔트리 는 글로벌 깊이 3비트로 다시 키핑되어 국부 깊이 2가 있는 D로 종료되며, 현재 3으로 증가하여 D와 E로 분할할 수 있다.
  5. 스플릿 버킷 D의 인 k2 {\2}}개의 내용이 3비트로 재키팅되어 D'로 끝난다
  6. K4는 재시도되고 결국 스페어 슬롯이 있는 E로 끝난다.
Extendible hashing 6.svg

Now, is in D and is tried again, with 3 bits 011.., and it points to bucket D which already contains so is full; D's local depth is 2 but now the global depth is 3 after the directory doubling, so now D can be split into bucket's D' and E, the contents of D, has its retried with a new global depth bitmask of 3 and ends up in D', then the new entry is retried with ) 비트 마스크가 3의 새로운 전역 깊이 비트 카운트를 사용하며 011이 제공되고 이 비트 마스크는 이제 비어 있는 새 버킷 E를 가리킨다.그래서 는 버킷 E로 들어간다.

구현 예

아래는 Python의 확장 가능한 해싱 알고리즘으로 디스크 블록/메모리 페이지 연결, 캐싱 및 일관성 문제가 제거되었다.깊이가 정수의 비트 크기를 초과하면 디렉터리를 두 배로 늘리거나 버킷을 분할하면 항목이 다른 버킷으로 다시 삭제되지 않기 때문에 문제가 있다는 점에 유의하십시오.

코드는 최하위 비트를 사용하므로 전체 디렉토리를 하나의 블록으로 복사할 수 있어 테이블 확장이 더욱 효율적이다(Ramakrishnan & Gehrke(2003)).

파이톤 예

페이지_SZ = 10  계급 페이지:     반항하다 __init___(자아의) -> 없음:         자아의.지도를 그리다 = []         자아의.local_deep = 0      반항하다 가득 찬(자아의) -> 바가지 긁다:         돌아오다 (자아의.지도를 그리다) >= 페이지_SZ      반항하다 놓다(자아의, k, v) -> 없음:         을 위해 i, (핵심을, 가치를 매기다)  열거하다(자아의.지도를 그리다):             만일 핵심을 == k:                 굴을 파다 자아의.지도를 그리다[i]                 부숴뜨리다         자아의.지도를 그리다.덧셈을((k, v))      반항하다 얻다(자아의, k):         을 위해 핵심을, 가치를 매기다  자아의.지도를 그리다:             만일 핵심을 == k:                 돌아오다 가치를 매기다      반항하다 get_local_high_bit(자아의):       돌아오다 1 << 자아의.local_deep  계급 익스텐더블 해싱:     반항하다 __init___(자아의) -> 없음:         자아의.global = 0         자아의.전화번호부 = [페이지()]      반항하다 get_page(자아의, k):         h = 해시하다(k)         돌아오다 자아의.전화번호부[h & ((1 << 자아의.global) - 1)]      반항하다 놓다(자아의, k, v) -> 없음:         p = 자아의.get_page(k)         가득 찬 = p.가득 찬()         p.놓다(k, v)         만일 가득 찬:             만일 p.local_deep == 자아의.global:                 자아의.전화번호부 *= 2                 자아의.global += 1              p0 = 페이지()             p1 = 페이지()             p0.local_deep = p1.local_deep = p.local_deep + 1             high_bit = p.get_local_high_bit()             을 위해 k2, v2  p.지도를 그리다:                 h = 해시하다(k2)                 new_p = p1 만일 h & high_bit 다른 p0                 new_p.놓다(k2, v2)              을 위해 i  범위(해시하다(k) & (high_bit - 1), (자아의.전화번호부), high_bit):                 자아의.전화번호부[i] = p1 만일 i & high_bit 다른 p0      반항하다 얻다(자아의, k):         돌아오다 자아의.get_page(k).얻다(k)  만일 __name__ == "__main__":      = 익스텐더블 해싱()     N = 10088     l = 리스트를 작성하다(범위(N))      수입하다 무작위의     무작위의.섞다(l)     을 위해 x  l:         .놓다(x, x)     인쇄하다(l)      을 위해 i  범위(N):         인쇄하다(.얻다(i)) 

메모들

  1. ^ 파긴연구진(1979년).
  2. ^ Mikuláš Patocka (2006). Design and Implementation of the Spad Filesystem (PDF) (Thesis). "제4.1.6절 확장 가능한 해싱: ZFS 및 GFS" 및 "표 4.1: 파일 시스템의 디렉토리 조직"

참고 항목

참조

  • Fagin, R.; Nievergelt, J.; Pippenger, N.; Strong, H. R. (September 1979), "Extendible Hashing - A Fast Access Method for Dynamic Files", ACM Transactions on Database Systems, 4 (3): 315–344, doi:10.1145/320083.320092, S2CID 2723596
  • Ramakrishnan, R.; Gehrke, J. (2003), Database Management Systems, 3rd Edition: Chapter 11, Hash-Based Indexing, pp. 373–378
  • Silberschatz, Abraham; Korth, Henry; Sudarshan, S., Database System Concepts, Sixth Edition: Chapter 11.7, Dynamic Hashing

외부 링크