Ruby使用GDBM操作DBM數(shù)據(jù)存儲方法實例詳解
DBM簡介
dbm(database manager) 是使用本地文件來存儲數(shù)據(jù)的數(shù)據(jù)庫,基于Key -Value對數(shù)據(jù)進行存儲、讀取,且有些dbm的實現(xiàn)( berkeley db)還支持BTree索引。dbm效率相對較高,甚至在某些情況下比關(guān)系型數(shù)據(jù)庫系統(tǒng)的速度還更高,因為幾乎所有dbm都支持比BTree效率要高的hash索引方式。
有多種dbm實現(xiàn):標(biāo)準(zhǔn)dbm、ndbm( new dbm)、gdbm(GNU DBM)、sdbm( small dbm)、Berkeley db等, gdbm是對ndbm的擴展,它支持緩存功能。
DBM數(shù)據(jù)存儲原理
- dbm的數(shù)據(jù)存取基于key-value的hash格式
- dbm/ndbm中,key單獨存放在一個文件中,key+value存放在另一個文件中。對于gdbm,則是key作為索引數(shù)據(jù)單獨存放在db文件中的一個地方(索引區(qū)),key+value存放在db文件中的另一個地方(數(shù)據(jù)區(qū))
- 為了高效率查詢,除了key作為索引單獨存放外,還額外存放key+value在db文件中的偏移位置以及大小,使得可以直接seek()跳轉(zhuǎn)到指定位置處讀取指定大小的數(shù)據(jù)
- 刪除記錄時,只是刪除索引區(qū)的key,數(shù)據(jù)區(qū)的key+value不方便刪除也沒必要刪除,數(shù)據(jù)區(qū)這段孤兒空間稱為保留空間或碎片空間,可以作為空閑空間留待后續(xù)復(fù)用
- gdbm在執(zhí)行讀取操作之后會將數(shù)據(jù)緩存下來,因此,第一次讀取可能速度慢,但是第二次速度將非???。keys、values等操作的的結(jié)果也都會被緩存下來
- 因為碎片空間可被復(fù)用,所以dbm還會記錄所有的碎片空間的位置以及大小,gdbm中以鏈表方式記錄之
- 因刪除記錄不會釋放空間,所以db文件大小不會減小。換句話說,dbm的文件會隨著時間的推移不斷增大,除非重組dbm,重組時,將根據(jù)索引區(qū)存在的key找到數(shù)據(jù)區(qū)所有對應(yīng)的key+value數(shù)據(jù),并將它們寫入臨時文件,最后重命名覆蓋原db文件
- 插入數(shù)據(jù)時,如果沒有碎片空間,默認將插入在尾部,如果中間有碎片空間,則判斷待寫入數(shù)據(jù)的大小是否能夠插入在碎片空間中
- 更新數(shù)據(jù)時,如果更新后的數(shù)據(jù)變大,且該數(shù)據(jù)后面沒有碎片空間,則直接原地移除并在文件尾部插入更新后的數(shù)據(jù),如果有足夠的空間存放更新后的數(shù)據(jù),則原地更新
- dbm只能存儲字符串,數(shù)值、布爾、對象等都不能直接存儲
Ruby使用gdbm
Ruby中要使用gdbm,它依賴于gdbm擴展庫和頭文件,所以需先安裝:
# sudo yum install gdbm-devel # Windows: #ridk exec uname -a確定32位還是64位, #然后ridk exec pacman -S mingw-w64-<$arch>-gdbm sudo apt install libgdbm-dev gem install gdbm
使用類方法GDBM.new()
或者GDBM.open()
可打開gdbm來操作db文件。
require 'gdbm' gdbm = GDBM.new("/tmp/lang.db") gdbm["perl"] = "Perl" gdbm["shell"] = "Shell" gdbm["php"] = "PHP" gdbm.close
查看其文件內(nèi)容:
$ ls -l /tmp/lang.db -rw-rw-rw- 1 longshuai longshuai 8192 May 17 21:22 /tmp/lang.db $ cat /tmp/lang.db P |...x...l9php...rdshe...}N;iperl...perlPerlshellShellphpPHP
其中…表示的是亂碼部分。
注意其大小為8K,且數(shù)據(jù)區(qū)默認在db文件的尾部,包含了key和value。
從db中檢索數(shù)據(jù):
gdbm = GDBM.open("/tmp/lang.db") pp gdbm["perl"] pp gdbm["php"] gdbm.close
new()、open()
new()或open():open()可給定語句塊,語句塊退出時自動關(guān)閉IO流,未給定語句塊時,open()等價于new()。
new(filename, mode = 0666, flags = nil) open(filename, mode = 0666, flags = nil) open(filename, mode = 0666, flags = nil) { |gdbm| ... }
當(dāng)指定要操作的db文件不存在時,會創(chuàng)建文件,可指定創(chuàng)建文件時的權(quán)限。此外,flag參數(shù)接受如下值:
### 注意:writer方式可讀可寫 READER - 以只讀方式打開,即返回一個reader WRITER - 以可讀寫方式打開,即返回一個writer WRCREAT - writer,如果數(shù)據(jù)庫文件不存在,則創(chuàng)建 NEWDB- writer,總是截斷覆蓋已存在的數(shù)據(jù)庫文件 # 上面的三個writer可使用位或(|)的方式結(jié)合下面的選項: SYNC- 以sync模式寫入數(shù)據(jù)庫文件 NOLOCK - 打開時不鎖定數(shù)據(jù)庫文件
在未給定任何選項時,即默認情況下,總是先嘗試以WRCREAT的方式打開,即以writer打開且文件不存在時創(chuàng)建。但如果打開失敗(比如另一個進程已經(jīng)打開且還未關(guān)閉),則嘗試使用reader方式打開。
reader和reader之間互相兼容,writer和writer之間以及writer和reader之間互斥。所以,在某一時刻,允許同時有多個reader,但只能有一個writer。
當(dāng)打開gdbm實例后,它可以按照操作hash結(jié)構(gòu)的方式去操作db,此外,gdbm已經(jīng)mix-in Enumerable模塊,所以可以直接使用該模塊中的一些方法,比如find、grep、map等。
gdbm方法
######### 查詢、插入、更新 ######### ["key"] fetch(key [, default]) → value 檢索指定的key。 使用`[]`檢索時,如果key不存在將返回nil, 使用fetch檢索時,如果key不存在則報錯,或者返回指定的默認值 values_at(key, ...) → array 檢索一個或多個key,并以數(shù)組方式返回對應(yīng)的value ["key"]= value store(key, value) → value 更新指定的key,如果key不存在則插入 ########## 遍歷 ######### each_pair { |key, value| block } → gdbm each_key { |key| block } → gdbm each_value { |value| block } → gdbm 分別根據(jù)key-value、key、value遍歷db ######### 其它檢索、篩選方式 ######### key(value) → key 根據(jù)value找到其key,如果有多個相同的value,返回第一個 keys → array 以數(shù)組方式返回db中所有的key values → array 以數(shù)組方式返回所有value select { |key, value| block } → array 篩選所有滿足條件的key-value ######### 判斷key或value是否存在 ######### has_key?(k) → true or false include?(k) → true or false key?(k) → true or false member?(k) → true or false 判斷key是否存在 has_value?(v) → true or false value?(v) → true or false 判斷指定的value是否存在 ######### 刪除 ######### delete(key) → value or nil 根據(jù)key移除key-value并返回被移除的Key-value,db若空,返回nil shift → (key, value) or nil 移除指定的key-value,并以數(shù)組方式返回之,db若空,則返回nil delete_if { |key, value| block } → gdbm 移除滿足條件(語句塊返回true)的key-value,直接修改gdbm reject { |key, value| block } → hash 等價于delete_if,但不修改gdbm,而是以hash的方式返回 reject! { |key, value| block } → gdbm 等價于delete_if,直接修改gdbm clear → gdbm 清空db中所有key-value ######## 大小判斷 ######### empty? → true or false db是否為空 length → fixnum size → fixnum 等價,返回db中的key-value數(shù)量 ####### 其它操作 ######### invert → hash 反轉(zhuǎn)gdbm中key-value:key作為value,value作為key,并以hash的方式返回 close → nil 關(guān)閉已打開的db文件 closed? → true or false 判斷db文件是否已關(guān)閉 replace(other) → gdbm 將另一個gdbm(即other)的內(nèi)容覆蓋替換到當(dāng)前的gdbm update(other) → gdbm 用另一個gdbm(即Other)合并到當(dāng)前gdbm,若key沖突,則當(dāng)前gdbm的key被覆蓋 reorganize → gdbm 重組gdbm cachesize = size → size 設(shè)置gdbm內(nèi)部的hash桶緩存大小 ######## gdbm模式 ######### sync → gdbm 將IO buffer中的數(shù)據(jù)刷入磁盤中的db文件,全部寫入成功才返回 如果以SYNC標(biāo)記打開,則無需sync() fastmode = boolean → boolean syncmode = boolean → boolean 打開或關(guān)閉sync模式。 sync模式下,寫入操作需要寫入磁盤db文件成功(或失敗)后才返回, 非sync模式下,只需寫入io buffer即可返回。 syncmode方法在gdbm >= 1.8才可用,在此版本之前,使用方法fastmode= ######### 轉(zhuǎn)換 ######### to_a → array to_hash → hash 轉(zhuǎn)換為數(shù)組、轉(zhuǎn)換為hash
更多關(guān)于Ruby使用GDBM操作DBM數(shù)據(jù)存儲的方法請查看下面的相關(guān)鏈接
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。