想要明白什麼是key/value數據庫

想要明白什麼是key/value數據庫,就必須瞭解哈希表(Hash Table)這種數據結構。
好比,Berkley DB就是典型的key/value數據庫。 算法

如下內容對哈希表進行了很形象的描述:
========================================
Google搜索到的頭條:散列表(也叫哈希表),是根據關鍵碼值直接進行訪問的數據結構,也就是說,它經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。
這個映射函數叫作散列函數,存放記錄的數組叫作散列表。 數據庫

這個解釋其實太含糊,想要整明白哈希表,那就得明白哈希表到底有什麼樣的優點。
數據結構中,有個時間算法複雜度O(n)的概念來衡量某種算法在時間效率上的優劣。
哈希表的理想算法複雜度爲O(1),也就是說利用哈希表查找某個值,系統所使用的時間在理想狀況下爲定值,這就是它的優點。
那麼哈希表是如何作到這一點的呢? 數組

咱們定義一個很大的有序數組,想要獲得位於該數組第n個位置的值,它的算法複雜度爲O(1)。
哈希表利用哈希函數將須要存儲的內容的關鍵值轉換爲這個有序數組中的某個值,在被存儲內容和有序數組之間創建了映射關係。
這樣,下次咱們對這個值進行查找時只要使用同一個哈希函數對關鍵值進行轉換,找到這個數組值 就能夠了。 數據結構

若是尚未明白是怎麼回事的話,那咱們來舉個例子。假設咱們要作個存儲結構,須要存儲下來三國中的人物,以及他們的詳細信息。
咱們用他們的名字來做爲存儲 的關鍵值,例如:劉備,曹操,孫權,關羽,張飛……等等。
這個時候咱們若是想用通常的方法來查找這些英雄豪傑,須要遍歷整個存儲空間,若是這些英雄豪傑一 共有n個,那麼這時候的時間算法複雜度爲O(n)。
顯然若是n值很大,每次想要找到某個英雄就須要比較長的時間。 函數

此時咱們先定義一個大的有序結構數組HashValue[m],用來存放各位英雄豪傑的信息。
而後編寫一個哈希函數ChangeToHashValue (name),函數的具體內容就不細說了,反正這個函數會將這些作爲關鍵值的名字轉換爲HashValue[m]中的某個下標值x。
而後能夠將英雄的信息 放進HashValue[x]中去。這樣,能夠將全部英雄的信息存儲起來。當查詢的時候再使用哈希函數ChangeToHashValue(name)獲得這個下標值,這樣就很容易獲得了這個英雄的信息。 性能

例如:ChangeToHashValue(劉備)爲10,那麼就將劉備存儲到HashValue [10]裏面。
當查詢的時候再次使用ChangeToHashValue(劉備)獲得10,這個時候咱們就能夠很容易找到劉備的全部信息。
在實際應用中若是咱們想把全部的英雄豪傑都存儲進系統時,須要定義m>n。
就是數組的大小要大於須要存儲的信息量,因此說哈希表是一個以空間換取時間的數據結構。 效率

這個時候問題來了,出現了這種狀況ChangeToHashValue(關羽)和ChangeToHashValue(張飛)獲得的值是同樣的,都 是250,咱們豈不是在存儲過程當中會遇到麻煩,怎麼安排他們二位的地方呢(總不能讓二位打一架,誰贏了誰呆在那吧),這就須要一個解決衝突的方法。
當遇到這種狀況時咱們能夠這樣處理,先存儲好了關羽,當張飛進入系統時會發現關羽已是250了,那咱就加一位,251得了,這不就解決了。
咱們查找張飛的時候也 是,一看250不是張飛,那就加個1,就找到了。
這時還存在一個問題,直接用ChangeToHashValue(趙雲)爲251,張飛已經早早佔了他的地方,那就再加1存到252唄。
呵呵,這時咱們會發現,當哈希函數衝突發生的機率很高時,可能會有一羣英雄豪傑在250這個值後面扎堆排隊。
要命的是查找的時候,時間算法複雜度早已不是O(1)了(因此咱們說理想狀況下哈希表的時間算法複雜度爲O(1))。 搜索

這就是說哈希函數的編寫是哈希表的一個關鍵問題,會涉及到一個存儲值在哈希表中的統計分佈。
若是哈希函數已經定義好了,衝突的解決就成爲了改變系統性能的關鍵因素。
其實還有不少種方法來解決衝突狀況下的存儲和查找問題,不必定非要線性向後排隊,若是有好的哈希表衝突的解決方法也能很大程度上提升系統的效率。 遍歷

相關文章
相關標籤/搜索