Ruby使用GDBM操作DBM數(shù)據(jù)存儲方法實(shí)例詳解
DBM簡介
dbm(database manager) 是使用本地文件來存儲數(shù)據(jù)的數(shù)據(jù)庫,基于Key -Value對數(shù)據(jù)進(jìn)行存儲、讀取,且有些dbm的實(shí)現(xiàn)( berkeley db)還支持BTree索引。dbm效率相對較高,甚至在某些情況下比關(guān)系型數(shù)據(jù)庫系統(tǒng)的速度還更高,因?yàn)閹缀跛衐bm都支持比BTree效率要高的hash索引方式。
有多種dbm實(shí)現(xiàn):標(biāo)準(zhǔn)dbm、ndbm( new dbm)、gdbm(GNU DBM)、sdbm( small dbm)、Berkeley db等, gdbm是對ndbm的擴(kuò)展,它支持緩存功能。
DBM數(shù)據(jù)存儲原理
- dbm的數(shù)據(jù)存取基于key-value的hash格式
- dbm/ndbm中,key單獨(dú)存放在一個(gè)文件中,key+value存放在另一個(gè)文件中。對于gdbm,則是key作為索引數(shù)據(jù)單獨(dú)存放在db文件中的一個(gè)地方(索引區(qū)),key+value存放在db文件中的另一個(gè)地方(數(shù)據(jù)區(qū))
- 為了高效率查詢,除了key作為索引單獨(dú)存放外,還額外存放key+value在db文件中的偏移位置以及大小,使得可以直接seek()跳轉(zhuǎn)到指定位置處讀取指定大小的數(shù)據(jù)
- 刪除記錄時(shí),只是刪除索引區(qū)的key,數(shù)據(jù)區(qū)的key+value不方便刪除也沒必要刪除,數(shù)據(jù)區(qū)這段孤兒空間稱為保留空間或碎片空間,可以作為空閑空間留待后續(xù)復(fù)用
- gdbm在執(zhí)行讀取操作之后會將數(shù)據(jù)緩存下來,因此,第一次讀取可能速度慢,但是第二次速度將非???。keys、values等操作的的結(jié)果也都會被緩存下來
- 因?yàn)樗槠臻g可被復(fù)用,所以dbm還會記錄所有的碎片空間的位置以及大小,gdbm中以鏈表方式記錄之
- 因刪除記錄不會釋放空間,所以db文件大小不會減小。換句話說,dbm的文件會隨著時(shí)間的推移不斷增大,除非重組dbm,重組時(shí),將根據(jù)索引區(qū)存在的key找到數(shù)據(jù)區(qū)所有對應(yīng)的key+value數(shù)據(jù),并將它們寫入臨時(shí)文件,最后重命名覆蓋原db文件
- 插入數(shù)據(jù)時(shí),如果沒有碎片空間,默認(rèn)將插入在尾部,如果中間有碎片空間,則判斷待寫入數(shù)據(jù)的大小是否能夠插入在碎片空間中
- 更新數(shù)據(jù)時(shí),如果更新后的數(shù)據(jù)變大,且該數(shù)據(jù)后面沒有碎片空間,則直接原地移除并在文件尾部插入更新后的數(shù)據(jù),如果有足夠的空間存放更新后的數(shù)據(jù),則原地更新
- dbm只能存儲字符串,數(shù)值、布爾、對象等都不能直接存儲
Ruby使用gdbm
Ruby中要使用gdbm,它依賴于gdbm擴(kuò)展庫和頭文件,所以需先安裝:
# 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ū)默認(rèn)在db文件的尾部,包含了key和value。
從db中檢索數(shù)據(jù):
gdbm = GDBM.open("/tmp/lang.db")
pp gdbm["perl"]
pp gdbm["php"]
gdbm.closenew()、open()
new()或open():open()可給定語句塊,語句塊退出時(shí)自動關(guān)閉IO流,未給定語句塊時(shí),open()等價(jià)于new()。
new(filename, mode = 0666, flags = nil)
open(filename, mode = 0666, flags = nil)
open(filename, mode = 0666, flags = nil) { |gdbm| ... }當(dāng)指定要操作的db文件不存在時(shí),會創(chuàng)建文件,可指定創(chuàng)建文件時(shí)的權(quán)限。此外,flag參數(shù)接受如下值:
### 注意:writer方式可讀可寫 READER - 以只讀方式打開,即返回一個(gè)reader WRITER - 以可讀寫方式打開,即返回一個(gè)writer WRCREAT - writer,如果數(shù)據(jù)庫文件不存在,則創(chuàng)建 NEWDB- writer,總是截?cái)喔采w已存在的數(shù)據(jù)庫文件 # 上面的三個(gè)writer可使用位或(|)的方式結(jié)合下面的選項(xiàng): SYNC- 以sync模式寫入數(shù)據(jù)庫文件 NOLOCK - 打開時(shí)不鎖定數(shù)據(jù)庫文件
在未給定任何選項(xiàng)時(shí),即默認(rèn)情況下,總是先嘗試以WRCREAT的方式打開,即以writer打開且文件不存在時(shí)創(chuàng)建。但如果打開失敗(比如另一個(gè)進(jìn)程已經(jīng)打開且還未關(guān)閉),則嘗試使用reader方式打開。
reader和reader之間互相兼容,writer和writer之間以及writer和reader之間互斥。所以,在某一時(shí)刻,允許同時(shí)有多個(gè)reader,但只能有一個(gè)writer。
當(dāng)打開gdbm實(shí)例后,它可以按照操作hash結(jié)構(gòu)的方式去操作db,此外,gdbm已經(jīng)mix-in Enumerable模塊,所以可以直接使用該模塊中的一些方法,比如find、grep、map等。
gdbm方法
######### 查詢、插入、更新 #########
["key"]
fetch(key [, default]) → value
檢索指定的key。
使用`[]`檢索時(shí),如果key不存在將返回nil,
使用fetch檢索時(shí),如果key不存在則報(bào)錯,或者返回指定的默認(rèn)值
values_at(key, ...) → array
檢索一個(gè)或多個(gè)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,如果有多個(gè)相同的value,返回第一個(gè)
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
等價(jià)于delete_if,但不修改gdbm,而是以hash的方式返回
reject! { |key, value| block } → gdbm
等價(jià)于delete_if,直接修改gdbm
clear → gdbm
清空db中所有key-value
######## 大小判斷 #########
empty? → true or false
db是否為空
length → fixnum
size → fixnum
等價(jià),返回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
將另一個(gè)gdbm(即other)的內(nèi)容覆蓋替換到當(dāng)前的gdbm
update(other) → gdbm
用另一個(gè)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)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信