本地数据存储 | wsztrush 

JerryXia 发表于 , 阅读 (0)

最近在考虑如何做算法的优化计算,有两个地方比较头疼:

  • 耗时
  • 内存

现在的做法是一股脑把所有的东西丢到内存,做起来简单,但是一个任务开跑400MB+的内存就没了,有点慌。并且,读取这400MB+的数据耗时也相当可观,如果能将数据放在本地,在执行任务的时候就地取材,应该也能省不少。

Chronicle

同时支持堆外和持久化。

用法&特点

在创建的时候如果是create则用堆外内存,如果是createPersistedTo(file)则能持久化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestMain {
@Test
public void test() throws Exception {
ChronicleMap<Integer, String> chronicleMap = ChronicleMap
.of(Integer.class, String.class)
.name("test-map")
.averageValue("123123")
.entries(10000)
.create();
for (int i = 0; i < 10000; i++) {
chronicleMap.put(i, "123");
}
}
}

原理

TODO

RocksDB

在LevelDB的基础开发,牺牲部分写性能,提升大量读性能。

用法&特点

基本的Kev/Value操作:

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
public class TestMain {
static {
RocksDB.loadLibrary();
}
@Test
public void test() throws Exception {
// INIT
Options options = new Options();
options.setCreateIfMissing(true);
RocksDB rocksDB = RocksDB.open(options, "/Users/tianchi.gzt/workspace/rocksdb/");
byte[] key = "key".getBytes(), value = "value".getBytes();
// PUT
rocksDB.put(key, value);
// GET
str(rocksDB.get(key));
// MULTI GET
Map<byte[], byte[]> ret = rocksDB.multiGet(Lists.newArrayList(key));
for (Map.Entry<byte[], byte[]> entry : ret.entrySet()) {
str(entry.getKey(), entry.getValue());
}
// ITER
RocksIterator iterator = rocksDB.newIterator();
for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) {
str(iterator.key(), iterator.value());
}
// DELETE
rocksDB.delete(key);
}
private void str(byte[]... bytes) {
List<String> content = Lists.newArrayList();
for (byte[] b : bytes) {
content.add(new String(b));
}
System.out.println(Joiner.on(' ').join(content));
}
}

此外增加了ColumnFamily用法,用来做隔离(可以分别配置),默认使用default

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
public class TestMain {
static {
RocksDB.loadLibrary();
}
@Test
public void test() throws Exception {
// INIT
Options options = new Options();
options.setCreateIfMissing(true);
String dbPath = "/Users/tianchi.gzt/workspace/rocksdb/";
// 设置DB中有哪些ColumnFamily
List<ColumnFamilyDescriptor> columnFamilyDescriptors = new ArrayList<>();
List<byte[]> columnFamilies = RocksDB.listColumnFamilies(options, dbPath);
if (columnFamilies.size() > 0) {
columnFamilies.forEach(cf -> columnFamilyDescriptors.add(new ColumnFamilyDescriptor(cf, new ColumnFamilyOptions())));
} else {
columnFamilyDescriptors.add(new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY, new ColumnFamilyOptions()));
}
// 链接DB
List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
DBOptions dbOptions = new DBOptions();
dbOptions.setCreateIfMissing(true);
RocksDB rocksDB = RocksDB.open(dbOptions, dbPath, columnFamilyDescriptors, columnFamilyHandles);
byte[] table = "table".getBytes(), key = "key".getBytes(), value = "value".getBytes();
// 如果已经有同名的,将其删除
for(int i = 0; i < columnFamilyDescriptors.size(); i++) {
if(new String(columnFamilyDescriptors.get(i).columnFamilyName()).equals(table)) {
rocksDB.dropColumnFamily(columnFamilyHandles.get(i));
}
}
// 创建ColumnFamily。
ColumnFamilyHandle columnFamilyHandle = rocksDB.createColumnFamily(new ColumnFamilyDescriptor(table, new ColumnFamilyOptions()));
// 插入
rocksDB.put(columnFamilyHandle, key, value);
// 读取
str(rocksDB.get(columnFamilyHandle, key));
}
private void str(byte[]... bytes) {
List<String> content = Lists.newArrayList();
for (byte[] b : bytes) {
content.add(new String(b));
}
System.out.println(Joiner.on(' ').join(content));
}
}

原理

TODO

SQLite

轻量级数据库(ACID),设计目标为嵌入式,占用资源非常低,支持语言非常广!

用法&特点

很“标准”的数据库方法方式,能通过SQL来快速实现一些功能,但是性能貌似并没有很好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TestMain {
@Test
public void test() throws Exception {
Connection connection = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:test.db");
stmt = connection.createStatement();
String sql = "CREATE TABLE COMPANY " +
"(ID INT PRIMARY KEY NOT NULL," +
" NAME TEXT NOT NULL, " +
" AGE INT NOT NULL, " +
" ADDRESS CHAR(50), " +
" SALARY REAL)";
stmt.executeUpdate(sql);
stmt.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

原理

TODO

参考