ego008 avatar

用嵌入式数据做碎片文件存储

🕥 by ego008

有很多小文件(10KB~200KB),不想直接保存在硬盘,要放在嵌入式数据库,个人对 leveldb 和 boltdb 比较熟悉,就用这两个嵌入式数据库做比较。

主要对占用空间对比

Bash: du
1
2
3
4
5
6
7
8
$ du -sh ./*
4.0K	./go.mod
4.0K	./go.sum
1.2G	./img
1.1G	./ldb
4.0K	./main.go
1.4G	./bdb
1.3G	./bdb2

结果如上

  • 原图片文件夹 img 1.2G
  • leveldb 文件夹 ldb 1.1G
  • boltdb 文件 bdb 1.4G
  • boltdb 文件,使用 snappy 压缩,bdb2 1.3G

snappy 对图片压缩率不大

leveldb 有分层文件,如下

plaintext: leveldb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ du -sh ./*
2.1M	./000007.ldb
2.6M	./000024.ldb
2.8M	./000026.ldb
2.3M	./000027.ldb
3.7M	./000034.ldb
4.2M	./000036.ldb
2.7M	./000038.ldb
2.3M	./000040.ldb
3.6M	./000044.ldb
3.4M	./000046.ldb
5.7M	./000048.ldb
5.7M	./000050.ldb
5.6M	./000054.ldb
6.9M	./000057.ldb
1.2M	./000058.ldb
4.4M	./000060.ldb
4.6M	./000062.ldb
3.7M	./000066.ldb

boltdb 只有一个超级无敌旋风大的单文件,这对日后转移有潜在麻烦。

go 测试代码

Go: dbimg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package main

import (
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/cespare/xxhash/v2"
	"github.com/ego008/sdb"
	"github.com/ego008/udb"
	"github.com/golang/snappy"
	"io/ioutil"
	"log"
)

var (
	ldb  *sdb.DB
	ydb  *udb.DB
	ydb2 *udb.DB
)

func Xxhash(s []byte) uint64 {
	return xxhash.Sum64(s)
}

func main() {
	var err error
	ldb, err = sdb.Open("ldb", nil)
	if err != nil {
		log.Fatalln(err)
	}
	defer func() {
		_ = ldb.Close()
	}()

	ydb, err = udb.Open("ydb")
	if err != nil {
		log.Fatalln(err)
	}

	defer func() {
		_ = ydb.Close()
	}()

	ydb2, err = udb.Open("ydb2")
	if err != nil {
		log.Fatalln(err)
	}

	defer func() {
		_ = ydb2.Close()
	}()

	c := 0
	tbn := "img"
	dir := "img"
	files, _ := ioutil.ReadDir(dir)
	for _, fi := range files {
		if fi.IsDir() {
			//
		} else {
			bt, err := ioutil.ReadFile(dir + "/" + fi.Name())
			if err != nil {
				log.Fatalln(err)
			}

			hsu := Xxhash(bt)
			key := sdb.I2b(hsu)

			if ldb.Hset(tbn, key, bt) != nil {
				log.Fatalln(err)
			}

			if ydb.Update(func(tx *bolt.Tx) error {
				return ydb.Hset(tx, tbn, key, bt)
			}) != nil {
				log.Fatalln(err)
			}

			if ydb2.Update(func(tx *bolt.Tx) error {
				return ydb2.Hset(tx, tbn, key, snappy.Encode(nil, bt))
			}) != nil {
				log.Fatalln(err)
			}
			//
			c++
		}
	}

	fmt.Println(c)
}

💘 相关文章

写一条评论

Based on Golang + fastHTTP + sdb | go1.16.5 Processed in 1ms