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

Page store: adding data to new database is now faster.

上级 7a0eb586
...@@ -9,6 +9,7 @@ package org.h2.store; ...@@ -9,6 +9,7 @@ package org.h2.store;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import org.h2.compress.CompressLZF; import org.h2.compress.CompressLZF;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
...@@ -26,6 +27,7 @@ import org.h2.util.IntIntHashMap; ...@@ -26,6 +27,7 @@ import org.h2.util.IntIntHashMap;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ObjectArray; import org.h2.util.ObjectArray;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueNull;
/** /**
* Transaction log mechanism. The stream contains a list of records. The data * Transaction log mechanism. The stream contains a list of records. The data
...@@ -45,8 +47,9 @@ public class PageLog { ...@@ -45,8 +47,9 @@ public class PageLog {
public static final int NOOP = 0; public static final int NOOP = 0;
/** /**
* An undo log entry. * An undo log entry. Format: page id: varInt, size, page. Size 0 means
* Format: page id: varInt, page. * uncompressed, size 1 means empty page, otherwise the size is the number
* of compressed bytes.
*/ */
public static final int UNDO = 1; public static final int UNDO = 1;
...@@ -255,6 +258,9 @@ public class PageLog { ...@@ -255,6 +258,9 @@ public class PageLog {
int size = in.readVarInt(); int size = in.readVarInt();
if (size == 0) { if (size == 0) {
in.readFully(data.getBytes(), 0, store.getPageSize()); in.readFully(data.getBytes(), 0, store.getPageSize());
} else if (size == 1) {
// empty
Arrays.fill(data.getBytes(), 0, store.getPageSize(), (byte) 0);
} else { } else {
in.readFully(compressBuffer, 0, size); in.readFully(compressBuffer, 0, size);
compress.expand(compressBuffer, 0, size, data.getBytes(), 0, store.getPageSize()); compress.expand(compressBuffer, 0, size, data.getBytes(), 0, store.getPageSize());
...@@ -423,6 +429,16 @@ public class PageLog { ...@@ -423,6 +429,16 @@ public class PageLog {
return row; return row;
} }
/**
* Check if the undo entry was already written for the given page.
*
* @param pageId the page
* @return true if it was written
*/
boolean getUndo(int pageId) {
return undo.get(pageId);
}
/** /**
* Add an undo entry to the log. The page data is only written once until * Add an undo entry to the log. The page data is only written once until
* the next checkpoint. * the next checkpoint.
...@@ -446,22 +462,26 @@ public class PageLog { ...@@ -446,22 +462,26 @@ public class PageLog {
Data buffer = getBuffer(); Data buffer = getBuffer();
buffer.writeByte((byte) UNDO); buffer.writeByte((byte) UNDO);
buffer.writeVarInt(pageId); buffer.writeVarInt(pageId);
int pageSize = store.getPageSize(); if (page.getBytes()[0] == 0) {
if (COMPRESS_UNDO) { buffer.writeVarInt(1);
int size = compress.compress(page.getBytes(), pageSize, compressBuffer, 0); } else {
if (size < pageSize) { int pageSize = store.getPageSize();
buffer.writeVarInt(size); if (COMPRESS_UNDO) {
buffer.checkCapacity(size); int size = compress.compress(page.getBytes(), pageSize, compressBuffer, 0);
buffer.write(compressBuffer, 0, size); if (size < pageSize) {
buffer.writeVarInt(size);
buffer.checkCapacity(size);
buffer.write(compressBuffer, 0, size);
} else {
buffer.writeVarInt(0);
buffer.checkCapacity(pageSize);
buffer.write(page.getBytes(), 0, pageSize);
}
} else { } else {
buffer.writeVarInt(0); buffer.writeVarInt(0);
buffer.checkCapacity(pageSize); buffer.checkCapacity(pageSize);
buffer.write(page.getBytes(), 0, pageSize); buffer.write(page.getBytes(), 0, pageSize);
} }
} else {
buffer.writeVarInt(0);
buffer.checkCapacity(pageSize);
buffer.write(page.getBytes(), 0, pageSize);
} }
write(buffer); write(buffer);
} catch (IOException e) { } catch (IOException e) {
...@@ -579,8 +599,19 @@ public class PageLog { ...@@ -579,8 +599,19 @@ public class PageLog {
int columns = row.getColumnCount(); int columns = row.getColumnCount();
data.writeVarInt(columns); data.writeVarInt(columns);
data.checkCapacity(row.getByteCount(data)); data.checkCapacity(row.getByteCount(data));
for (int i = 0; i < columns; i++) { if (session.isRedoLogBinaryEnabled()) {
data.writeValue(row.getValue(i)); for (int i = 0; i < columns; i++) {
data.writeValue(row.getValue(i));
}
} else {
for (int i = 0; i < columns; i++) {
Value v = row.getValue(i);
if (v.getType() == Value.BYTES) {
data.writeValue(ValueNull.INSTANCE);
} else {
data.writeValue(v);
}
}
} }
Data buffer = getBuffer(); Data buffer = getBuffer();
buffer.writeByte((byte) (add ? ADD : REMOVE)); buffer.writeByte((byte) (add ? ADD : REMOVE));
......
...@@ -137,8 +137,8 @@ public class PageStore implements CacheWriter { ...@@ -137,8 +137,8 @@ public class PageStore implements CacheWriter {
private static final int INCREMENT_PAGES = 128; private static final int INCREMENT_PAGES = 128;
private static final int READ_VERSION = 2; private static final int READ_VERSION = 3;
private static final int WRITE_VERSION = 2; private static final int WRITE_VERSION = 3;
private static final int META_TYPE_SCAN_INDEX = 0; private static final int META_TYPE_SCAN_INDEX = 0;
private static final int META_TYPE_BTREE_INDEX = 1; private static final int META_TYPE_BTREE_INDEX = 1;
...@@ -203,6 +203,8 @@ public class PageStore implements CacheWriter { ...@@ -203,6 +203,8 @@ public class PageStore implements CacheWriter {
*/ */
private int changeCount = 1; private int changeCount = 1;
private Data emptyPage;
/** /**
* Create a new page store object. * Create a new page store object.
* *
...@@ -632,6 +634,7 @@ public class PageStore implements CacheWriter { ...@@ -632,6 +634,7 @@ public class PageStore implements CacheWriter {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, fileName); throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, fileName);
} }
pageSize = size; pageSize = size;
emptyPage = createData();
pageSizeShift = shift; pageSizeShift = shift;
} }
...@@ -665,7 +668,7 @@ public class PageStore implements CacheWriter { ...@@ -665,7 +668,7 @@ public class PageStore implements CacheWriter {
private void writeVariableHeader() throws SQLException { private void writeVariableHeader() throws SQLException {
Data page = createData(); Data page = createData();
page.writeInt(0); page.writeInt(0);
page.writeLong(writeCount); page.writeLong(getWriteCountTotal());
page.writeInt(logKey); page.writeInt(logKey);
page.writeInt(logFirstTrunkPage); page.writeInt(logFirstTrunkPage);
page.writeInt(logFirstDataPage); page.writeInt(logFirstDataPage);
...@@ -739,10 +742,12 @@ public class PageStore implements CacheWriter { ...@@ -739,10 +742,12 @@ public class PageStore implements CacheWriter {
database.checkWritingAllowed(); database.checkWritingAllowed();
if (!recoveryRunning) { if (!recoveryRunning) {
int pos = record.getPos(); int pos = record.getPos();
if (old == null) { if (!log.getUndo(pos)) {
old = readPage(pos); if (old == null) {
old = readPage(pos);
}
log.addUndo(pos, old);
} }
log.addUndo(pos, old);
} }
} }
} }
...@@ -847,7 +852,11 @@ public class PageStore implements CacheWriter { ...@@ -847,7 +852,11 @@ public class PageStore implements CacheWriter {
* @return the page id * @return the page id
*/ */
public int allocatePage() throws SQLException { public int allocatePage() throws SQLException {
return allocatePage(null, 0); int pos = allocatePage(null, 0);
if (!recoveryRunning) {
log.addUndo(pos, emptyPage);
}
return pos;
} }
private int allocatePage(BitField exclude, int first) throws SQLException { private int allocatePage(BitField exclude, int first) throws SQLException {
......
...@@ -1015,6 +1015,8 @@ public class Recover extends Tool implements DataHandler { ...@@ -1015,6 +1015,8 @@ public class Recover extends Tool implements DataHandler {
byte[] data = new byte[pageSize]; byte[] data = new byte[pageSize];
if (size == 0) { if (size == 0) {
in.readFully(data, 0, pageSize); in.readFully(data, 0, pageSize);
} else if (size == 1) {
// empty
} else { } else {
byte[] compressBuffer = new byte[size]; byte[] compressBuffer = new byte[size];
in.readFully(compressBuffer, 0, size); in.readFully(compressBuffer, 0, size);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论