提交 22e6097b authored 作者: Thomas Mueller's avatar Thomas Mueller

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

上级 91516b70
...@@ -50,9 +50,12 @@ public class LobStorage { ...@@ -50,9 +50,12 @@ public class LobStorage {
private static final String LOB_DATA = "INFORMATION_SCHEMA.LOB_DATA"; private static final String LOB_DATA = "INFORMATION_SCHEMA.LOB_DATA";
private static final int BLOCK_LENGTH = 20000; private static final int BLOCK_LENGTH = 20000;
private static final boolean HASH = true;
// each entry needs 16 bytes (2 longs) /**
private static final int HASH_CACHE_SIZE = 8 * 1024; * The size of cache for lob block hashes. Each entry needs 2 longs (16
* bytes), therefore, the size 4096 means 64 KB.
*/
private static final int HASH_CACHE_SIZE = 4 * 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;
...@@ -83,9 +86,9 @@ public class LobStorage { ...@@ -83,9 +86,9 @@ public class LobStorage {
// stat.execute("SET UNDO_LOG 0"); // stat.execute("SET UNDO_LOG 0");
// stat.execute("SET REDO_LOG_BINARY 0"); // stat.execute("SET REDO_LOG_BINARY 0");
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, HASH 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, HASH INT, DATA BINARY) HIDDEN"); stat.execute("CREATE TABLE IF NOT EXISTS " + LOB_DATA + "(BLOCK BIGINT PRIMARY KEY, COMPRESSED 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();
...@@ -268,19 +271,26 @@ public class LobStorage { ...@@ -268,19 +271,26 @@ public class LobStorage {
private void deleteLob(long lob) throws SQLException { private void deleteLob(long lob) throws SQLException {
PreparedStatement prep; PreparedStatement prep;
prep = prepare(
"SELECT BLOCK, HASH FROM " + LOB_MAP + " D WHERE D.LOB = ? " +
"AND NOT EXISTS(SELECT 1 FROM " + LOB_MAP + " O " +
"WHERE O.BLOCK = D.BLOCK AND O.LOB <> ?)");
prep.setLong(1, lob);
prep.setLong(2, lob);
ResultSet rs = prep.executeQuery();
prep = prepare( prep = prepare(
"DELETE FROM " + LOB_MAP + " " + "DELETE FROM " + LOB_MAP + " " +
"WHERE LOB = ?"); "WHERE LOB = ?");
prep.setLong(1, lob); prep.setLong(1, lob);
prep.execute(); prep.execute();
prep = prepare( while (rs.next()) {
"DELETE FROM " + LOB_DATA + " D " + long block = rs.getLong(1);
"WHERE BLOCK IN(SELECT M.BLOCK FROM " + LOB_MAP + " M WHERE LOB = ?) " + int hash = rs.getInt(2);
"AND NOT EXISTS(SELECT 1 FROM " + LOB_MAP + " M " + setHashCacheBlock(hash, -1);
"WHERE M.BLOCK = D.BLOCK AND M.LOB <> ?)"); prep = prepare("DELETE FROM " + LOB_DATA + " WHERE BLOCK = ?");
prep.setLong(1, lob); prep.setLong(1, block);
prep.setLong(2, lob);
prep.execute(); prep.execute();
}
prep = prepare( prep = prepare(
"DELETE FROM " + LOBS + " " + "DELETE FROM " + LOBS + " " +
"WHERE ID = ?"); "WHERE ID = ?");
...@@ -371,8 +381,8 @@ public class LobStorage { ...@@ -371,8 +381,8 @@ public class LobStorage {
try { try {
long lobId = getNextLobId(); long lobId = getNextLobId();
PreparedStatement prep = prepare( PreparedStatement prep = prepare(
"INSERT INTO " + LOB_MAP + "(LOB, SEQ, BLOCK) " + "INSERT INTO " + LOB_MAP + "(LOB, SEQ, HASH, BLOCK) " +
"SELECT ?, SEQ, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?"); "SELECT ?, SEQ, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?");
prep.setLong(1, lobId); prep.setLong(1, lobId);
prep.setLong(2, oldLobId); prep.setLong(2, oldLobId);
prep.executeUpdate(); prep.executeUpdate();
...@@ -390,6 +400,25 @@ public class LobStorage { ...@@ -390,6 +400,25 @@ public class LobStorage {
} }
} }
private long getHashCacheBlock(int hash) {
if (HASH_CACHE_SIZE > 0) {
int index = (int) (hash & (HASH_CACHE_SIZE - 1));
long oldHash = hashBlocks[index];
if (oldHash == hash) {
return hashBlocks[index + HASH_CACHE_SIZE];
}
}
return -1;
}
private void setHashCacheBlock(int hash, long block) {
if (HASH_CACHE_SIZE > 0) {
int index = (int) (hash & (HASH_CACHE_SIZE - 1));
hashBlocks[index] = hash;
hashBlocks[index + HASH_CACHE_SIZE] = block;
}
}
/** /**
* Store a block in the LOB storage. * Store a block in the LOB storage.
* *
...@@ -405,50 +434,37 @@ public class LobStorage { ...@@ -405,50 +434,37 @@ public class LobStorage {
b = compress.compress(b, compressAlgorithm); b = compress.compress(b, compressAlgorithm);
} }
int hash = Arrays.hashCode(b); int hash = Arrays.hashCode(b);
if (HASH) { block = getHashCacheBlock(hash);
block = 0; if (block != -1) {
int index = hash & (HASH_CACHE_SIZE - 1);
long oldHash = hashBlocks[index];
int hashTableAddWhenReading;
int hashTableRemoveWhenDeleting;
if (oldHash == hash) {
long old = hashBlocks[index + HASH_CACHE_SIZE];
PreparedStatement prep = prepare( PreparedStatement prep = prepare(
"SELECT COMPRESSED, DATA FROM " + LOB_DATA + "SELECT COMPRESSED, DATA FROM " + LOB_DATA +
" WHERE BLOCK = ?"); " WHERE BLOCK = ?");
prep.setLong(1, old); prep.setLong(1, block);
ResultSet rs = prep.executeQuery(); ResultSet rs = prep.executeQuery();
if (rs.next()) { if (rs.next()) {
boolean compressed = rs.getInt(1) != 0; boolean compressed = rs.getInt(1) != 0;
byte[] compare = rs.getBytes(2); byte[] compare = rs.getBytes(2);
if (Arrays.equals(b, compare) && compressed == (compressAlgorithm != null)) { if (compressed == (compressAlgorithm != null) && Arrays.equals(b, compare)) {
blockExists = true; blockExists = true;
block = old;
} }
} }
} }
if (!blockExists) { if (!blockExists) {
block = nextBlock++; block = nextBlock++;
} setHashCacheBlock(hash, block);
hashBlocks[index] = hash;
hashBlocks[index + HASH_CACHE_SIZE] = block;
} else {
block = nextBlock++;
}
if (!blockExists) {
PreparedStatement prep = prepare( PreparedStatement prep = prepare(
"INSERT INTO " + LOB_DATA + "(BLOCK, COMPRESSED, HASH, DATA) VALUES(?, ?, ?, ?)"); "INSERT INTO " + LOB_DATA + "(BLOCK, COMPRESSED, 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.setInt(3, hash); prep.setBytes(3, b);
prep.setBytes(4, b);
prep.execute(); prep.execute();
} }
PreparedStatement prep = prepare( PreparedStatement prep = prepare(
"INSERT INTO " + LOB_MAP + "(LOB, SEQ, BLOCK) VALUES(?, ?, ?)"); "INSERT INTO " + LOB_MAP + "(LOB, SEQ, HASH, BLOCK) VALUES(?, ?, ?, ?)");
prep.setLong(1, lobId); prep.setLong(1, lobId);
prep.setInt(2, seq); prep.setInt(2, seq);
prep.setLong(3, block); prep.setLong(3, hash);
prep.setLong(4, block);
prep.execute(); prep.execute();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论