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

New LOB storage.

上级 9259aadc
...@@ -16,10 +16,12 @@ import java.sql.PreparedStatement; ...@@ -16,10 +16,12 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList;
import java.util.Random; import java.util.Random;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.util.New;
import org.h2.util.Utils; import org.h2.util.Utils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -76,12 +78,11 @@ public class TestLob { ...@@ -76,12 +78,11 @@ public class TestLob {
*/ */
static class LobInputStream extends InputStream { static class LobInputStream extends InputStream {
private byte[] buffer = new byte[BLOCK_LENGTH]; private byte[] buffer;
private int pos;
private PreparedStatement prepSelectBlock; private PreparedStatement prepSelectBlock;
private int bufferEnd;
private long remaining; private long remaining;
private long next; private long next;
private int pos;
LobInputStream(PreparedStatement prepSelectBlock, long first, long length) { LobInputStream(PreparedStatement prepSelectBlock, long first, long length) {
this.next = first; this.next = first;
...@@ -91,9 +92,10 @@ public class TestLob { ...@@ -91,9 +92,10 @@ public class TestLob {
public int read() throws IOException { public int read() throws IOException {
fillBuffer(); fillBuffer();
if (pos >= bufferEnd) { if (remaining <= 0) {
return -1; return -1;
} }
remaining--;
return buffer[pos++] & 255; return buffer[pos++] & 255;
} }
...@@ -110,33 +112,31 @@ public class TestLob { ...@@ -110,33 +112,31 @@ public class TestLob {
return 0; return 0;
} }
int read = 0; int read = 0;
int todo; while (length > 0) {
// while (length > 0) { fillBuffer();
// fillBuffer(); if (remaining <= 0) {
// break;
// if (r < 0) { }
// break; int len = (int) Math.min(length, remaining);
// } len = Math.min(len, buffer.length - pos);
// read += r; System.arraycopy(buffer, pos, buff, off, len);
// off += r; read += len;
// len -= r; remaining -= len;
// } off += len;
// return read == 0 ? -1 : read; length -= len;
// }
// int len = 0; return read == 0 ? -1 : read;
// while (length > 0 && remaining > 0) {
// }
return read;
} }
private void fillBuffer() throws IOException { private void fillBuffer() throws IOException {
if (buffer != null && pos < bufferEnd) { if (buffer != null && pos < buffer.length) {
return; return;
} }
if (remaining <= 0) { if (remaining <= 0) {
return; return;
} }
try { try {
// select id, next, data from block where id = ?
prepSelectBlock.setLong(1, next); prepSelectBlock.setLong(1, next);
ResultSet rs = prepSelectBlock.executeQuery(); ResultSet rs = prepSelectBlock.executeQuery();
if (!rs.next()) { if (!rs.next()) {
...@@ -145,12 +145,13 @@ public class TestLob { ...@@ -145,12 +145,13 @@ public class TestLob {
io.initCause(e); io.initCause(e);
throw e; throw e;
} }
next = rs.getLong(2);
buffer = rs.getBytes(3);
pos = 0;
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convertToIOException(e); throw DbException.convertToIOException(e);
} }
int todo; // compress / decompress
//
//
// int len = readInt(); // int len = readInt();
// if (decompress == null) { // if (decompress == null) {
// // EOF // // EOF
...@@ -190,7 +191,33 @@ public class TestLob { ...@@ -190,7 +191,33 @@ public class TestLob {
init(c); init(c);
c = DriverManager.getConnection("jdbc:h2:data/test"); c = DriverManager.getConnection("jdbc:h2:data/test");
int len = 128 * 1024; // int len = 10 * 1024 * 1024;
// block: 1394
// regular: 725
// int len = 16 * 1024;
// block: 1817
// regular: 4552
int len = 32 * 1024;
// block: 1770
// regular: 2255
// int len = 64 * 1024;
// block: 1776
// regular: 1385
// 1024 * 1024
// block: 1682
// regular: 455
// int len = 128 * 1024;
// block: 1516
// regular: 1020
int repeat = 6;
int count = (int) (52428800L / len);
byte[] buff = new byte[len]; byte[] buff = new byte[len];
Random random = new Random(1); Random random = new Random(1);
random.nextBytes(buff); random.nextBytes(buff);
...@@ -213,21 +240,52 @@ public class TestLob { ...@@ -213,21 +240,52 @@ public class TestLob {
// Profiler prof = new Profiler(); // Profiler prof = new Profiler();
// prof.setInterval(1); // prof.setInterval(1);
// prof.startCollecting(); // prof.startCollecting();
int x = 0; int x = 0, y = 0;
for (int j = 0; j < 6; j++) { ArrayList<LobId> list = New.arrayList();
for (int j = 0; j < repeat; j++) {
boolean regular = (j & 1) == 1; boolean regular = (j & 1) == 1;
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
for (int i = 0; i < 400; i++) { for (int i = 0; i < count; i++) {
prep.setInt(1, x++);
if (regular) { if (regular) {
prep.setInt(1, x++);
prep.setBinaryStream(2, new ByteArrayInputStream(buff), len); prep.setBinaryStream(2, new ByteArrayInputStream(buff), len);
prep.execute(); prep.execute();
} else { } else {
addLob(new ByteArrayInputStream(buff), -1, -1); LobId id = addLob(new ByteArrayInputStream(buff), -1, -1);
list.add(id);
}
}
System.out.println((regular ? "regular: " : "block: ") + (System.currentTimeMillis() - time));
}
System.out.println("read------------");
x = 0;
y = 0;
prep = conn.prepareStatement("select data from test where id = ?");
byte[] buff2 = new byte[1024];
for (int j = 0; j < repeat; j++) {
boolean regular = (j & 1) == 1;
long time = System.currentTimeMillis();
for (int i = 0; i < count * 10; i++) {
InputStream in2;
if (regular) {
prep.setInt(1, x++ % repeat);
ResultSet rs = prep.executeQuery();
rs.next();
in2 = rs.getBinaryStream(1);
} else {
in2 = getInputStream(list.get(y++ % repeat));
}
while (true) {
int len2 = in2.read(buff2);
if (len2 < 0) {
break;
}
} }
} }
System.out.println((regular ? "regular: " : "block: ") + (System.currentTimeMillis() - time)); System.out.println((regular ? "regular: " : "block: ") + (System.currentTimeMillis() - time));
} }
// prof.stopCollecting(); // prof.stopCollecting();
// System.out.println(prof.getTop(5)); // System.out.println(prof.getTop(5));
c.close(); c.close();
...@@ -236,7 +294,7 @@ public class TestLob { ...@@ -236,7 +294,7 @@ public class TestLob {
private void init(Connection newConn) throws SQLException { private void init(Connection newConn) throws SQLException {
this.conn = newConn; this.conn = newConn;
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
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");
// TODO support incremental garbage collection // TODO support incremental garbage collection
stat.execute("create table if not exists block(id bigint primary key, next bigint, data binary)"); stat.execute("create table if not exists block(id bigint primary key, next bigint, data binary)");
...@@ -248,12 +306,17 @@ public class TestLob { ...@@ -248,12 +306,17 @@ public class TestLob {
rs = stat.executeQuery("select max(id) from lob"); rs = stat.executeQuery("select max(id) from lob");
rs.next(); rs.next();
nextLob = rs.getLong(1) + 1; nextLob = rs.getLong(1) + 1;
prepInsertBlock = conn.prepareStatement("insert into block values(?, ?, ?)"); prepInsertBlock = conn.prepareStatement("insert into block(id, next, data) values(?, ?, ?)");
prepDeleteBlock = conn.prepareStatement("delete from block where id = ?"); prepDeleteBlock = conn.prepareStatement("delete from block where id = ?");
prepInsertLob = conn.prepareStatement("insert into lob values(?, ?, ?, ?)"); prepDeleteLob = conn.prepareStatement("delete from lob where id = ?");
prepInsertLob = conn.prepareStatement("insert into lob(id, length, block, table) values(?, ?, ?, ?)");
prepSelectBlock = conn.prepareStatement("select id, next, data from block where id = ?"); prepSelectBlock = conn.prepareStatement("select id, next, data from block where id = ?");
} }
private void deleteLob(int lobId) {
//
}
private LobId addLob(InputStream in, long maxLength, int table) throws SQLException { private LobId addLob(InputStream in, long maxLength, int table) throws SQLException {
byte[][] buff = new byte[2][BLOCK_LENGTH]; byte[][] buff = new byte[2][BLOCK_LENGTH];
if (maxLength < 0) { if (maxLength < 0) {
...@@ -272,16 +335,19 @@ public class TestLob { ...@@ -272,16 +335,19 @@ public class TestLob {
length += len; length += len;
maxLength -= len; maxLength -= len;
if (blockId > 0) { if (blockId > 0) {
// insert into block(id, next, data) values(?, ?, ?)
prepInsertBlock.setLong(1, nextBlock++); prepInsertBlock.setLong(1, nextBlock++);
prepInsertBlock.setLong(2, nextBlock); prepInsertBlock.setLong(2, nextBlock);
prepInsertBlock.setBytes(3, buff[(blockId - 1) & 1]); prepInsertBlock.setBytes(3, buff[(blockId - 1) & 1]);
prepInsertBlock.execute(); prepInsertBlock.execute();
} }
} }
// insert into block(id, next, data) values(?, ?, ?)
prepInsertBlock.setLong(1, nextBlock++); prepInsertBlock.setLong(1, nextBlock++);
prepInsertBlock.setLong(2, firstBlock); prepInsertBlock.setLong(2, firstBlock);
prepInsertBlock.setBytes(3, buff[(blockId - 1) & 1]); prepInsertBlock.setBytes(3, buff[(blockId - 1) & 1]);
prepInsertBlock.execute(); prepInsertBlock.execute();
// insert into lob(id, length, block, table) values(?, ?, ?, ?)
prepInsertLob.setLong(1, lob); prepInsertLob.setLong(1, lob);
prepInsertLob.setLong(2, length); prepInsertLob.setLong(2, length);
prepInsertLob.setLong(3, firstBlock); prepInsertLob.setLong(3, firstBlock);
...@@ -302,6 +368,7 @@ public class TestLob { ...@@ -302,6 +368,7 @@ public class TestLob {
private void deleteBlocks(long first, long last) throws SQLException { private void deleteBlocks(long first, long last) throws SQLException {
for (long id = first; id <= last; id++) { for (long id = first; id <= last; id++) {
// delete from block where id = ?
prepDeleteBlock.setLong(1, id); prepDeleteBlock.setLong(1, id);
prepDeleteBlock.execute(); prepDeleteBlock.execute();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论