一、簡介
BoltDB是一個純Go語言編寫的可嵌入式數據庫,它的數據被組織成一個B+樹的結構,用於提供高效、可靠的本地數據存儲服務。Bolt採用了MVCC(多版本並發控制)的處理方式,從而可以支持同時進行多個事務並發讀寫操作,而不是像一些其他的數據庫採用的加鎖方式。
Bolt的特徵有:支持ACID事務;鍵值對數據存儲方式;可排序查詢結果;支持內存映射的文件方式進行存儲;完全兼容Go的並發操作。
二、BoltDB的基本操作
1、打開和關閉數據庫的連接:
db, err := bolt.Open("mydb.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
2、增加或更新數據:
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
if err != nil {
return err
}
err = b.Put([]byte("hello"), []byte("world"))
return err
})
3、查詢數據:
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
v := b.Get([]byte("hello"))
fmt.Printf("value=%s\n", v)
return nil
})
4、刪除數據:
db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
err := b.Delete([]byte("hello"))
return err
})
三、BoltDB的索引和排序
BoltDB支持對數據進行索引和排序,我們可以在創建數據桶時通過設置BucketOption來實現索引和排序。例如:
options := bolt.DefaultOptions
options.NooSync = true
options.NoFreelistSync = true
db, err := bolt.Open("my.db", 0600, options)
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
if err != nil {
return err
}
// 創建索引
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
b2, err := tx.CreateBucketIfNotExists([]byte("IndexBucket"))
if err != nil {
return err
}
if err := b2.Put(v, k); err != nil {
return err
}
}
// 創建排序
c2 := b.Cursor()
var keys [][]byte
for k, _ := c2.First(); k != nil; k, _ = c2.Next() {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return bytes.Compare(keys[i], keys[j]) < 0
})
return nil
})
四、BoltDB的事務處理
在Bolt中,所有的寫操作都需要在一個事務中進行。當我們使用db.Update()方法時,這個方法會創建一個新的只寫事務,以此來執行我們的修改操作,同時我們也可以執行讀操作,但是需要注意的是,讀操作只能讀取到事務開始時的那個快照。
如果我們需要進行只讀操作,我們要使用db.View()方法,這個方法會創建一個只讀事務,其能夠讀取到最近的已提交快照。
db, err := bolt.Open("my.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 開始寫入事務
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
if err != nil {
return err
}
// 添加數據
if err := b.Put([]byte("apple"), []byte("red")); err != nil {
return err
}
// 添加數據
if err := b.Put([]byte("banana"), []byte("yellow")); err != nil {
return err
}
return nil
})
// 開始讀取事務
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
v := b.Get([]byte("apple"))
fmt.Printf("value=%s\n", v)
return nil
})
五、BoltDB的性能測試
我們來對Bolt進行一次性能測試:
package main
import (
"fmt"
"log"
"time"
"github.com/boltdb/bolt"
)
func main() {
// 打開BoltDB
db, err := bolt.Open("my.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 寫入1000000條數據
start := time.Now()
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
if err != nil {
return err
}
for i := 0; i < 1000000; i++ {
key := fmt.Sprintf("key-%d", i)
value := []byte("value")
if err := b.Put([]byte(key), value); err != nil {
return err
}
}
return nil
})
end := time.Now()
fmt.Printf("寫入1000000條數據,用時:%v\n", end.Sub(start))
// 讀取1000000條數據
start = time.Now()
db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("MyBucket"))
for i := 0; i < 1000000; i++ {
key := fmt.Sprintf("key-%d", i)
_ = b.Get([]byte(key))
}
return nil
})
end = time.Now()
fmt.Printf("讀取1000000條數據,用時:%v\n", end.Sub(start))
}
執行結果如下:
寫入1000000條數據,用時:5.1054857s 讀取1000000條數據,用時:125.025682ms
我們可以看到,Bolt在寫入1000000條數據時使用5秒左右,而讀取1000000條數據則只需要125毫秒,這表明Bolt在進行數據的讀取及存儲時有着非常好的性能表現。
原創文章,作者:OTXD,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/142263.html
微信掃一掃
支付寶掃一掃