提交 b9cafa06 authored 作者: Thomas Mueller's avatar Thomas Mueller

Storing lobs in the database has been changed. It is now faster.

上级 cedcc7ae
...@@ -51,11 +51,13 @@ public class LobStorage { ...@@ -51,11 +51,13 @@ public class LobStorage {
private static final int BLOCK_LENGTH = 20000; private static final int BLOCK_LENGTH = 20000;
private static final boolean HASH = true; private static final boolean HASH = true;
private static final long UNIQUE = 0xffff; // each entry needs 16 bytes (2 longs)
private static final int HASH_CACHE_SIZE = 8 * 1024;
private Connection conn; private Connection conn;
private HashMap<String, PreparedStatement> prepared = New.hashMap(); private HashMap<String, PreparedStatement> prepared = New.hashMap();
private long nextBlock; private long nextBlock;
private CompressTool compress = CompressTool.getInstance(); private CompressTool compress = CompressTool.getInstance();
private long[] hashBlocks = new long[HASH_CACHE_SIZE * 2];
private final DataHandler handler; private final DataHandler handler;
private boolean init; private boolean init;
...@@ -83,14 +85,11 @@ public class LobStorage { ...@@ -83,14 +85,11 @@ public class LobStorage {
stat.execute("CREATE TABLE IF NOT EXISTS " + LOBS + "(ID BIGINT PRIMARY KEY, BYTE_COUNT BIGINT, TABLE INT) HIDDEN"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOBS + "(ID BIGINT PRIMARY KEY, BYTE_COUNT BIGINT, TABLE INT) HIDDEN");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_MAP + "(LOB BIGINT, SEQ INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ)) HIDDEN"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_MAP + "(LOB BIGINT, SEQ INT, BLOCK BIGINT, PRIMARY KEY(LOB, SEQ)) HIDDEN");
stat.execute("CREATE INDEX IF NOT EXISTS INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON " + LOB_MAP + "(BLOCK, LOB)"); stat.execute("CREATE INDEX IF NOT EXISTS INFORMATION_SCHEMA.INDEX_LOB_MAP_DATA_LOB ON " + LOB_MAP + "(BLOCK, LOB)");
stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_DATA + "(BLOCK BIGINT PRIMARY KEY, COMPRESSED INT, DATA BINARY) HIDDEN"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_DATA + "(BLOCK BIGINT PRIMARY KEY, COMPRESSED INT, HASH INT, DATA BINARY) HIDDEN");
ResultSet rs; ResultSet rs;
rs = stat.executeQuery("SELECT MAX(BLOCK) FROM " + LOB_DATA); rs = stat.executeQuery("SELECT MAX(BLOCK) FROM " + LOB_DATA);
rs.next(); rs.next();
nextBlock = rs.getLong(1) + 1; nextBlock = rs.getLong(1) + 1;
if (HASH) {
nextBlock = Math.max(UNIQUE + 1, nextBlock);
}
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} }
...@@ -405,31 +404,44 @@ public class LobStorage { ...@@ -405,31 +404,44 @@ public class LobStorage {
if (compressAlgorithm != null) { if (compressAlgorithm != null) {
b = compress.compress(b, compressAlgorithm); b = compress.compress(b, compressAlgorithm);
} }
int hash = Arrays.hashCode(b);
if (HASH) { if (HASH) {
block = Arrays.hashCode(b) & UNIQUE; block = 0;
PreparedStatement prep = prepare( int index = hash & (HASH_CACHE_SIZE - 1);
"SELECT COMPRESSED, DATA FROM " + LOB_DATA + long oldHash = hashBlocks[index];
" WHERE BLOCK = ?"); int hashTableAddWhenReading;
prep.setLong(1, block); int hashTableRemoveWhenDeleting;
ResultSet rs = prep.executeQuery(); if (oldHash == hash) {
if (rs.next()) { long old = hashBlocks[index + HASH_CACHE_SIZE];
boolean compressed = rs.getInt(1) != 0; PreparedStatement prep = prepare(
byte[] compare = rs.getBytes(2); "SELECT COMPRESSED, DATA FROM " + LOB_DATA +
if (Arrays.equals(b, compare) && compressed == (compressAlgorithm != null)) { " WHERE BLOCK = ?");
blockExists = true; prep.setLong(1, old);
} else { ResultSet rs = prep.executeQuery();
block = nextBlock++; if (rs.next()) {
boolean compressed = rs.getInt(1) != 0;
byte[] compare = rs.getBytes(2);
if (Arrays.equals(b, compare) && compressed == (compressAlgorithm != null)) {
blockExists = true;
block = old;
}
} }
} }
if (!blockExists) {
block = nextBlock++;
}
hashBlocks[index] = hash;
hashBlocks[index + HASH_CACHE_SIZE] = block;
} else { } else {
block = nextBlock++; block = nextBlock++;
} }
if (!blockExists) { if (!blockExists) {
PreparedStatement prep = prepare( PreparedStatement prep = prepare(
"INSERT INTO " + LOB_DATA + "(BLOCK, COMPRESSED, DATA) VALUES(?, ?, ?)"); "INSERT INTO " + LOB_DATA + "(BLOCK, COMPRESSED, HASH, DATA) VALUES(?, ?, ?, ?)");
prep.setLong(1, block); prep.setLong(1, block);
prep.setInt(2, compressAlgorithm == null ? 0 : 1); prep.setInt(2, compressAlgorithm == null ? 0 : 1);
prep.setBytes(3, b); prep.setInt(3, hash);
prep.setBytes(4, b);
prep.execute(); prep.execute();
} }
PreparedStatement prep = prepare( PreparedStatement prep = prepare(
......
...@@ -44,6 +44,7 @@ public class TestLob extends TestBase { ...@@ -44,6 +44,7 @@ public class TestLob extends TestBase {
* @param a ignored * @param a ignored
*/ */
public static void main(String... a) throws Exception { public static void main(String... a) throws Exception {
System.setProperty("h2.lobInDatabase", "true");
TestBase.createCaller().init().test(); TestBase.createCaller().init().test();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论