青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

那誰的技術(shù)博客

感興趣領(lǐng)域:高性能服務(wù)器編程,存儲,算法,Linux內(nèi)核
隨筆 - 210, 文章 - 0, 評論 - 1183, 引用 - 0
數(shù)據(jù)加載中……

tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程

這一節(jié)關(guān)注TC中的hash數(shù)據(jù)庫如何根據(jù)一個key查找到該key所在的record,因為后續(xù)的刪除,插入記錄都是以查找為基礎(chǔ)的,所以首先描述這部分內(nèi)容.

從上一節(jié)的概述中,可以看到record結(jié)構(gòu)體中有兩個成員left,right:
typedef struct {                         // type of structure for a record
  uint64_t off;                          // offset of the record
  uint32_t rsiz;                         // size of the whole record
  uint8_t magic;                         // magic number
  uint8_t hash;                          // second hash value
  uint64_t left;                         // offset of the left child record
  uint64_t right;                        // offset of the right child record
  uint32_t ksiz;                         // size of the key
  uint32_t vsiz;                         // size of the value
  uint16_t psiz;                         // size of the padding
  const char *kbuf;                      // pointer to the key
  const char *vbuf;                      // pointer to the value
  uint64_t boff;                         // offset of the body
  char *bbuf;                            // buffer of the body
} TCHREC;
說明,每個record是存放在一個類二叉樹的結(jié)構(gòu)中的.

實際上,TC會首先根據(jù)一個record的key去算出該key所在的bucket index以及hash index,代碼如下:
/* Get the bucket index of a record.
   `hdb' specifies the hash database object.
   `kbuf' specifies the pointer to the region of the key.
   `ksiz' specifies the size of the region of the key.
   `hp' specifies the pointer to the variable into which the second hash value is assigned.
   The return value is the bucket index. 
*/
static uint64_t tchdbbidx(TCHDB *hdb, const char *kbuf, int ksiz, uint8_t *hp){
  assert(hdb 
&& kbuf && ksiz >= 0 && hp);
  uint64_t idx 
= 19780211;
  uint32_t hash 
= 751;
  
const char *rp = kbuf + ksiz;
  
while(ksiz--){
    idx 
= idx * 37 + *(uint8_t *)kbuf++;
    hash 
= (hash * 31^ *(uint8_t *)--rp;
  }
  
*hp = hash;
  
return idx % hdb->bnum;
}
需要特別提醒的一點是,上面的算法中,根據(jù)key算出所在的bucket index,是經(jīng)過模TCHDB->bnum之后的結(jié)果,也就是說,這個值是有限制的---最大不能超過TCHDB初始化時得到的bucket最大數(shù)量;而算出的二級hash值,我是沒有看出來有數(shù)值上的限制的,為什么?看了后面的內(nèi)容就明白了.

因此,所有根據(jù)記錄的key算出bucket index相同的記錄全都以二叉樹的形式組織起來,而每個bucket array元素存放的整型值就是該bucket樹根所在記錄的offset.

到此,相關(guān)的結(jié)構(gòu)體聯(lián)系都清楚了,下面的流程圖給出了查找一個key的記錄是否存在的流程:


簡單的解釋一下,這個查找的流程就是首先根據(jù)查找的key算出所在的bucket,然后在這個bucket的二叉樹中按照條件遍歷的過程.

前面提到過,bucket array是整個被mmap映射到共享內(nèi)存中去的.我們來做一個估計,假設(shè)存放bucket array的內(nèi)存使用了1G,而真正存放record的文件長度有16G,也就是,bucket array的元素與記錄大概是1:16的關(guān)系,假設(shè)所選的hash算法足夠的好,以至于每個記錄的key可以較為平均的分布在不同的bucket index上,也就是每個bucket array的元素組成的二叉樹上平均有16個元素,那么也就最多需要O(4)次讀取文件I/O(每次去讀取記錄的數(shù)據(jù)都是一次讀磁盤操作) + O(1)次內(nèi)存讀操作(因為需要在bucket array中得到樹根元素的offset).

但是等等,上面還有一些細節(jié)沒有交待清楚.

首先,上面的二叉樹不是類似AVL,紅黑樹這樣的平衡二叉查找樹,也就是說,很可能在極端的情況下演變成一個鏈表---樹的一邊沒有元素,另一邊有全部的元素.
其次,上面的流程圖中還有一點就是每次比較首先比較的是hash值,這個值的奧秘就在于解決上面提到的那個問題.既然只是一個普通的二叉樹,無法保證平衡,那么就通過算出這個二級的hash值來保證平衡---當(dāng)然,前提依然是所選擇的hash算法足夠的好,可以保證key平均的分布.

前面提到過,非平衡的二叉樹只會在極端的情況下才會演變?yōu)橐粋€極端不平衡的二叉樹--鏈表,而諸如AVL,紅黑樹之類的平衡二叉樹,算法編碼都相對復(fù)雜,調(diào)試起來也麻煩,出錯了要跟進更麻煩,另外還別忘了,這些平衡二叉樹之所以能保持平衡,在刪除/增加元素時做的讓樹重新平衡的操作,比如旋轉(zhuǎn)等,都是要涉及到讀寫樹結(jié)點的,而這些,目前都是存放在磁盤上的---也就是這是相對較費時的操作,所以問題在于:是不是值得為這一個極端的情況去優(yōu)化?另外,引入二級hash就是為了部分解決這個極端不平衡問題,它的思路簡單也容易實現(xiàn),但是引入的另外一個問題就是每次查找時根據(jù)key去算bucket index的時候,還要耗費時間去算hash index了.

平衡點,還是平衡點.時間還是空間,這是一個問題.

所以,經(jīng)過對TC的hash數(shù)據(jù)庫查找key流程的分析,最大的感受是:它沒有使用復(fù)雜的算法與數(shù)據(jù)結(jié)構(gòu),而是通過一些巧妙的優(yōu)化如二級hash的引入,達到了系統(tǒng)效率和編碼調(diào)試復(fù)雜度之間一個較好的平衡.學(xué)會"平衡"各種因素,是做項目做事情,都要掌握的一個技能,而這個,只有多經(jīng)歷多想才能慢慢積累了.

好了,簡單的回顧整個查找key的關(guān)鍵點:
1) 所有的record是以二叉樹的形式組織在同一個bucket上面的.
2) 這個二叉樹不是平衡的二叉樹
3) 為了解決問題二造成的極端不平衡問題,TC引入了二級hash,以保證這個二叉樹盡可能的平衡.

以上,就是TC對記錄,bucket的組織情況,以及整個查找算法的流程.可以看到,算法,結(jié)構(gòu)體定義等等都不復(fù)雜,但是由于巧妙的構(gòu)思,既可以使用盡可能簡單的算法/數(shù)據(jù)結(jié)構(gòu),又能規(guī)避可能出現(xiàn)的一些隱患,同時還能保證查找的高效率.

查找是key-value形式存儲的核心流程,能夠?qū)⑦@個流程優(yōu)化,對整個系統(tǒng)的性能也有很大的影響.



posted on 2010-01-12 19:25 那誰 閱讀(6644) 評論(6)  編輯 收藏 引用 所屬分類: tokyo cabinet

評論

# re: tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程  回復(fù)  更多評論   

找到工作了嗎?呵呵
2010-01-12 19:26 | code

# re: tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程  回復(fù)  更多評論   

@code
汗,你這個回復(fù)也太快了吧.
呵呵,周四去面試.
2010-01-12 19:29 | 那誰

# re: tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程  回復(fù)  更多評論   

汗啊,發(fā)現(xiàn)TC的設(shè)計和我之前用于分詞的XDB詞典,以前最近所思考的以crc32值計算后先做比較而期待是否能得到近似平橫的二叉樹,很接近!

實際測試后(用連續(xù)的1,2,3...作key或隨機生成的字符串做key分別測試)
用crc32大體能保持相對于根結(jié)點的左右子樹元素平橫,樹的高度也能平橫,但樹的高度卻是平橫樹的2倍左右。。。

也就是說 2萬個元素就會達到 32 左右的樹高,這樣感覺價值不大所以立即放棄,看上去還是要用B+樹才比較好。
2010-02-01 23:16 | hightman

# re: tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程  回復(fù)  更多評論   

由此看出來其實tc的設(shè)計還有好多地方可以改進的,包括它的hash計算(好多的乘法運算。。。完全沒必要以自己的生日作初始值,可以試著參考經(jīng)典高效的hash算法嘛),據(jù)某文章說該作者還比較自戀的,曾經(jīng)在sourceforge的主頁上設(shè)置隨機的<title>,每句都是“最xxx,頂級xxx。。。”類似的含義。


對了還有一次疑或bucket array的長度是否在創(chuàng)建數(shù)據(jù)庫時就確定下來了的?
2010-02-01 23:22 | hightman

# re: tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程  回復(fù)  更多評論   

你看的是tc哪個版本?
我看的是tokyocabinet-1.4.45,tcutil.c中hash鏈的實現(xiàn),作者使用的是平衡樹啊,splay-tree伸展樹
2011-03-15 17:43 | wtommy

# re: tokyocabinet1.4.19閱讀筆記(二)hash數(shù)據(jù)庫查找key流程  回復(fù)  更多評論   

您這個就是說,在 key 1 有重復(fù)值。這個需要您進去數(shù)據(jù)庫把之前的記錄給刪除,要不就在新的記錄改一下 key 1。<a href=http://www.mbtshoe-sales.com/>mbt outlet</a>
2011-03-29 13:37 | key 1
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久婷婷久久| 欧美性事在线| 激情文学综合丁香| 国产欧美一区二区视频| 国产精品视频久久| 国产午夜亚洲精品不卡| 国产亚洲欧美aaaa| 伊人春色精品| 亚洲乱码国产乱码精品精可以看 | 欧美中文字幕不卡| 老司机精品福利视频| 美女视频黄免费的久久| 亚洲高清不卡| 99国产精品视频免费观看一公开| 在线视频一区二区| 久久视频在线视频| 欧美色精品在线视频| 国产日产亚洲精品系列| 91久久精品美女| 亚洲欧美一区二区三区久久 | 在线一区欧美| 久久性天堂网| 一区二区毛片| 美女视频黄免费的久久| 国产精品日韩一区二区三区| 有坂深雪在线一区| 性高湖久久久久久久久| 亚洲国产精品一区在线观看不卡| 亚洲一区三区视频在线观看 | 欧美精品v日韩精品v韩国精品v| 国产精品久久| 99国产精品久久| 老司机精品久久| 亚洲一区在线免费观看| 欧美激情一区二区在线| 亚洲美女免费精品视频在线观看| 国产精品无人区| 欧美福利视频在线| 国产日韩亚洲| 亚洲欧美日韩精品综合在线观看| 欧美不卡一区| 欧美一区二区三区视频在线| 欧美无砖砖区免费| 一本一道久久综合狠狠老精东影业| 久久久久久久国产| 亚洲专区在线| 国产精品成人aaaaa网站| 亚洲欧洲精品一区二区| 另类亚洲自拍| 久久精品中文字幕一区| 国产亚洲一区二区在线观看| 亚洲天堂网站在线观看视频| 91久久精品国产91久久性色| 美女精品自拍一二三四| 亚洲国产精品成人| 免费看av成人| 嫩草影视亚洲| 日韩视频在线免费观看| 亚洲精美视频| 欧美日本一区二区三区| 在线视频精品| 99re6热在线精品视频播放速度 | 久久婷婷麻豆| 在线不卡中文字幕播放| 久久午夜视频| 久久中文在线| 亚洲人成网站999久久久综合| 欧美大片国产精品| 欧美成人按摩| 一区二区三区免费网站| 一区二区三区日韩欧美精品| 国产精品久久福利| 欧美在线电影| 久久噜噜亚洲综合| 亚洲日本精品国产第一区| 亚洲第一中文字幕在线观看| 欧美成人日韩| 亚洲欧美综合国产精品一区| 欧美亚洲午夜视频在线观看| 伊人狠狠色j香婷婷综合| 亚洲大黄网站| 国产精品国产三级国产a| 欧美专区在线观看一区| 久久成人av少妇免费| 亚洲综合国产精品| 国模私拍视频一区| 亚洲第一黄网| 国产精品社区| 免费亚洲电影在线| 欧美日韩国产系列| 久久国产精彩视频| 欧美大片在线观看一区| 欧美日韩一区在线观看视频| 亚洲欧美日韩另类| 久久久亚洲精品一区二区三区| 亚洲精品永久免费精品| 亚洲在线国产日韩欧美| 亚洲国产精品成人va在线观看| 日韩一级黄色av| 狠狠色狠狠色综合日日五| 亚洲精品一二区| 国产资源精品在线观看| 99视频一区二区| 在线日韩av片| 亚洲欧美在线高清| 99这里只有久久精品视频| 欧美在线免费观看| 亚洲天堂av在线免费| 久久精品日韩| 性做久久久久久免费观看欧美| 欧美sm视频| 看片网站欧美日韩| 国产欧美韩国高清| 中国成人黄色视屏| 日韩一级片网址| 久久女同互慰一区二区三区| 欧美一级片久久久久久久 | 国内精品一区二区三区| 日韩视频在线观看一区二区| 亚洲国产日韩一区| 久久久久久久综合| 久久九九久久九九| 国产欧美在线| 亚洲一二三级电影| 亚洲性感美女99在线| 欧美人成网站| 亚洲三级电影全部在线观看高清| 亚洲福利精品| 亚洲国产欧美不卡在线观看| 国产一区二区三区视频在线观看| 亚洲一区日韩在线| 亚洲一区二区三区高清| 欧美日韩高清在线观看| 亚洲三级电影全部在线观看高清| 亚洲国产精品悠悠久久琪琪| 久久精品女人的天堂av| 久久综合给合| 18成人免费观看视频| 久久亚洲精品网站| 亚洲国产高清一区| 日韩一级裸体免费视频| 欧美色欧美亚洲另类二区| 一本色道久久综合亚洲精品小说| 亚洲性线免费观看视频成熟| 国产精品国产三级国产普通话99 | 在线观看欧美一区| 久热re这里精品视频在线6| 美女图片一区二区| 亚洲精品1234| 欧美特黄a级高清免费大片a级| 亚洲免费观看高清完整版在线观看| 99成人在线| 国产精品嫩草99a| 午夜精品久久久久久久| 久久久www成人免费无遮挡大片 | 新狼窝色av性久久久久久| 欧美一区二区三区在| 久久久99爱| 亚洲国产精品精华液2区45 | 欧美风情在线观看| 亚洲午夜激情| 老司机凹凸av亚洲导航| 日韩一区二区精品在线观看| 欧美性大战xxxxx久久久| 欧美一级久久久| 亚洲黄色免费网站| 亚洲欧美日本日韩| 亚洲国产成人久久| 国产精品成人aaaaa网站| 久久精品综合| 9l视频自拍蝌蚪9l视频成人| 久久久精品日韩| 在线一区日本视频| 精品成人国产在线观看男人呻吟| 欧美国产高清| 午夜精品国产更新| 亚洲看片免费| 麻豆久久精品| 午夜精彩国产免费不卡不顿大片| 在线精品一区二区| 国产精品网站一区| 欧美高清在线一区| 久久精品视频免费观看| 亚洲视频欧洲视频| 亚洲激情欧美激情| 久久伊人精品天天| 亚洲欧美日韩在线一区| 亚洲茄子视频| 一区二区三区自拍| 国产欧美亚洲一区| 欧美视频精品一区| 欧美精品在线一区二区三区| 欧美在线高清| 亚洲免费影视第一页| 亚洲久久一区| 亚洲激情成人在线| 欧美高清在线一区| 乱码第一页成人| 欧美在线在线| 午夜在线不卡|