About Hash Collision
수까락님의 블로그에서 관심있는 부분을 다시 요약함.
출처 : http://sweeper.egloos.com/925740
Hash Collision
좋은 해쉬 함수는 해쉬 테이블, 해쉬맵등의 성능 향상에 필수적인 요소들이다.
질 낮은 해쉬 함수는 데이터들의 key를 같은 bucket에 유도하는 경우가 많아짐으로써 충동리 증가하게 되고, 이는 곧 해쉬테이블/맵의 성능 저하로 이어진다.
100만개의 크기를 가지는 해쉬 테이블에 뛰어난 해쉬 함수로 가지고 있다고 해도, 대략 2500개의 레코드가 찼을 때 충돌이 발생활 확률은 95%에 이른다고 한다.출처:Hash table
충돌이 발생했을때 이를 해결 할 수 있는 방안으로 chainning, open addressing 방식이 널리 사용된다.
Chaining
모든 bucket을 linked-list로 만들어 충돌이 발생하면 해당 bucket의 list에 해당 아이템을 추가하는 방식이다.
- 장점
1) 삭제 작업이 간단하다.
2) 모든 bucket이 사용중이더라도 충돌된 아이템 추가에 따른 성능 저하가 더디게 나타난다.
3) 효과적으로 구현이 간단. 기본 자료구조정도만 요구
4) 클러스터링에 영향을 받지 않아 충돌 최소화에만 집중할 수 있다.
5) 테이블(bucket을 위한)이 채워져도 성능저하가 linear하게 발생
6) 데이터의 크기가 5words and more라면 open-addressing보다 적은 메모리를 사용한다 - 단점
1) 충돌이 발생하지 않는 경우라면 bucket의 list길이가 대부분 짧은 상태이며, 이런 경우 linked-list가 가지는 오버헤드가 부담이 된다.
Open Addressing
배열내에 데이터를 바로 저장할 수 있다.
충돌은 probing 방식으로 해결하며 이를 위해 다음 probe sequence를 사용한다
- Linear probing
비어있는 bucket을 찾을때까지 순차적으로 탐색.
최악의 경우 탐색을 시작한 위치까지 돌아오게되어 종료된다.
캐쉬효율이 좋다.데이터의 클러스터링에 가장 취약한 단점 - Quadratic probing
2차 함수를 이용해 탐색할 위치를 찾는다.
캐쉬효율, 클러스터링 강점면에서는 중간정도 - Double hashing probing
하나의 해수함수에 충돌발생시 2차 해쉬함수 이용하여 새로운 주소 할당
캐쉬 효율을 좋지 않으나 클러스터링에 거의 영향을 받지 않는다
연산량이 많다
- 장점
1) 포인터를 저장할 필요가 없다(->serialization용이) 테이블 외부에 어떠한 추가공간이 필요없어 chaining방식보다 메모리 효율이 높다
2) 삽입시 메모리 할당 오버헤드가 없다.
3) 별도의 외부공간(linked-list 같은)이 필요없다.
4) 사용하는 데이터가 테이블에 모두 저장될 수 있고, 캐쉬라인에 적합할정도의 데이터크기가 작을 수도록 성능이 좋다
Coleasced hasing
Chaining, Open-Addressing 혼합방식
테이블의 bucket끼리 서로 chain 링크를 갖는다. -> 테이블 슬록보다 많은 수의 데이터를 저장할 수 없다.
hash의 단점
데이터를 pseudo-random 위치에 저장하기 때문에 데이터를 정렬된 순서로 접근하는 것에 엄청난 비용이 발생한다.
해쉬테이블은 일반적으로 locality-of-reference(하나의 자원에 여러번 접근하는 process)에 취약. 데이터 수가 적고 key type이 integer처럼 비교 비용이 적게 든다면 linear search를 하는 배열 같은 자료구조가 lookup에 더 나은 성능을 보인다.