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

New experimental page store.

上级 d83c77cd
...@@ -11,6 +11,7 @@ import org.h2.constant.ErrorCode; ...@@ -11,6 +11,7 @@ import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.TraceSystem;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.DataPage; import org.h2.store.DataPage;
......
...@@ -8,6 +8,7 @@ package org.h2.index; ...@@ -8,6 +8,7 @@ package org.h2.index;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.DataPage; import org.h2.store.DataPage;
...@@ -70,7 +71,17 @@ class PageBtreeLeaf extends PageBtree { ...@@ -70,7 +71,17 @@ class PageBtreeLeaf extends PageBtree {
return (entryCount / 2) + 1; return (entryCount / 2) + 1;
} }
onlyPosition = true; onlyPosition = true;
// change the offsets (now storing only positions)
int o = pageSize;
for (int i = 0; i < entryCount; i++) {
o -= index.getRowSize(data, getRow(i), onlyPosition);
offsets[i] = o;
}
last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
rowLength = index.getRowSize(data, row, onlyPosition); rowLength = index.getRowSize(data, row, onlyPosition);
if (SysProperties.CHECK && last - rowLength < start + OFFSET_LENGTH) {
throw Message.throwInternalError();
}
} }
written = false; written = false;
int offset = last - rowLength; int offset = last - rowLength;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.index; package org.h2.index;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.DataPage; import org.h2.store.DataPage;
...@@ -68,7 +69,6 @@ class PageBtreeNode extends PageBtree { ...@@ -68,7 +69,6 @@ class PageBtreeNode extends PageBtree {
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) { if (last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) {
int todoSplitAtLastInsertionPoint;
return (entryCount / 2) + 1; return (entryCount / 2) + 1;
} }
return 0; return 0;
...@@ -86,9 +86,18 @@ class PageBtreeNode extends PageBtree { ...@@ -86,9 +86,18 @@ class PageBtreeNode extends PageBtree {
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) { if (last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) {
// TODO remap all children
onlyPosition = true; onlyPosition = true;
// change the offsets (now storing only positions)
int o = pageSize;
for (int i = 0; i < entryCount; i++) {
o -= index.getRowSize(data, getRow(i), onlyPosition);
offsets[i] = o;
}
last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
rowLength = index.getRowSize(data, row, onlyPosition); rowLength = index.getRowSize(data, row, onlyPosition);
if (SysProperties.CHECK && last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) {
throw Message.throwInternalError();
}
} }
int offset = last - rowLength; int offset = last - rowLength;
int[] newOffsets = new int[entryCount + 1]; int[] newOffsets = new int[entryCount + 1];
......
...@@ -92,7 +92,6 @@ class PageDataLeaf extends PageData { ...@@ -92,7 +92,6 @@ class PageDataLeaf extends PageData {
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (entryCount > 0 && last - rowLength < start + KEY_OFFSET_PAIR_LENGTH) { if (entryCount > 0 && last - rowLength < start + KEY_OFFSET_PAIR_LENGTH) {
int todoSplitAtLastInsertionPoint;
return (entryCount / 2) + 1; return (entryCount / 2) + 1;
} }
int offset = last - rowLength; int offset = last - rowLength;
......
...@@ -87,7 +87,6 @@ class PageDataNode extends PageData { ...@@ -87,7 +87,6 @@ class PageDataNode extends PageData {
} }
int maxEntries = (index.getPageStore().getPageSize() - ENTRY_START) / ENTRY_LENGTH; int maxEntries = (index.getPageStore().getPageSize() - ENTRY_START) / ENTRY_LENGTH;
if (entryCount >= maxEntries) { if (entryCount >= maxEntries) {
int todoSplitAtLastInsertionPoint;
return entryCount / 2; return entryCount / 2;
} }
int pivot = page.getKey(splitPoint - 1); int pivot = page.getKey(splitPoint - 1);
...@@ -155,7 +154,6 @@ class PageDataNode extends PageData { ...@@ -155,7 +154,6 @@ class PageDataNode extends PageData {
} }
int getLastKey() throws SQLException { int getLastKey() throws SQLException {
int todoRemove;
return index.getPage(childPageIds[entryCount], getPos()).getLastKey(); return index.getPage(childPageIds[entryCount], getPos()).getLastKey();
} }
......
...@@ -139,6 +139,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -139,6 +139,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
store.updateRecord(newRoot, true, null); store.updateRecord(newRoot, true, null);
root = newRoot; root = newRoot;
} }
row.setDeleted(false);
if (database.isMultiVersion()) { if (database.isMultiVersion()) {
if (delta == null) { if (delta == null) {
delta = New.hashSet(); delta = New.hashSet();
...@@ -347,6 +348,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -347,6 +348,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("close"); trace.debug("close");
} }
if (delta != null) {
delta.clear();
}
rowCountDiff = 0;
if (sessionRowCount != null) {
sessionRowCount.clear();
}
int todoWhyNotClose; int todoWhyNotClose;
// store = null; // store = null;
int writeRowCount; int writeRowCount;
......
...@@ -461,7 +461,6 @@ public class PageLog { ...@@ -461,7 +461,6 @@ public class PageLog {
row.setLastLog(logId, logPos); row.setLastLog(logId, logPos);
data.reset(); data.reset();
int todoWriteIntoOutputDirectly;
row.write(data); row.write(data);
out.write(add ? ADD : REMOVE); out.write(add ? ADD : REMOVE);
out.writeInt(session.getId()); out.writeInt(session.getId());
......
...@@ -112,6 +112,8 @@ public class PageStore implements CacheWriter { ...@@ -112,6 +112,8 @@ public class PageStore implements CacheWriter {
// TODO PageData and PageBtree addRowTry: try to simplify // TODO PageData and PageBtree addRowTry: try to simplify
// TODO performance: don't save direct parent in btree nodes (only root) // TODO performance: don't save direct parent in btree nodes (only root)
// TODO space re-use: run TestPerformance multiple times, size should stay // TODO space re-use: run TestPerformance multiple times, size should stay
// TODO when inserting many rows, do not split at (entryCount / 2) + 1
// TODO maybe split at the last insertion point
// TODO when removing DiskFile: // TODO when removing DiskFile:
// remove CacheObject.blockCount // remove CacheObject.blockCount
......
...@@ -59,6 +59,7 @@ import org.h2.util.StringUtils; ...@@ -59,6 +59,7 @@ import org.h2.util.StringUtils;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
import org.h2.util.Tool; import org.h2.util.Tool;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLob; import org.h2.value.ValueLob;
/** /**
...@@ -296,11 +297,10 @@ public class Recover extends Tool implements DataHandler { ...@@ -296,11 +297,10 @@ public class Recover extends Tool implements DataHandler {
} }
/** /**
* Dumps the database. * Dumps the contents of a database to a SQL script file.
* *
* @param dir the directory * @param dir the directory
* @param db the database name (null for all databases) * @param db the database name (null for all databases)
* @throws SQLException
*/ */
public static void execute(String dir, String db) throws SQLException { public static void execute(String dir, String db) throws SQLException {
new Recover().process(dir, db); new Recover().process(dir, db);
...@@ -805,8 +805,8 @@ public class Recover extends Tool implements DataHandler { ...@@ -805,8 +805,8 @@ public class Recover extends Tool implements DataHandler {
break; break;
case Page.TYPE_DATA_NODE: { case Page.TYPE_DATA_NODE: {
int entries = s.readShortInt(); int entries = s.readShortInt();
int recordCount = s.readInt(); int rowCount = s.readInt();
writer.println("-- page " + page + ": data node " + (last ? "(last)" : "") + " entries: " + entries + " record: " + recordCount); writer.println("-- page " + page + ": data node " + (last ? "(last)" : "") + " entries: " + entries + " rowCount: " + rowCount);
break; break;
} }
case Page.TYPE_DATA_LEAF: { case Page.TYPE_DATA_LEAF: {
...@@ -819,16 +819,18 @@ public class Recover extends Tool implements DataHandler { ...@@ -819,16 +819,18 @@ public class Recover extends Tool implements DataHandler {
case Page.TYPE_BTREE_NODE: case Page.TYPE_BTREE_NODE:
writer.println("-- page " + page + ": btree node" + (last ? "(last)" : "")); writer.println("-- page " + page + ": btree node" + (last ? "(last)" : ""));
if (trace) { if (trace) {
dumpPageBtreeNode(writer, s); dumpPageBtreeNode(writer, s, !last);
} }
break; break;
case Page.TYPE_BTREE_LEAF: case Page.TYPE_BTREE_LEAF: {
setStorage(s.readInt()); setStorage(s.readInt());
writer.println("-- page " + page + ": btree leaf " + (last ? "(last)" : "") + " table: " + storageId); int entries = s.readShortInt();
writer.println("-- page " + page + ": btree leaf " + (last ? "(last)" : "") + " table: " + storageId + " entries: " + entries);
if (trace) { if (trace) {
dumpPageBtreeLeaf(writer, s); dumpPageBtreeLeaf(writer, s, entries, !last);
} }
break; break;
}
case Page.TYPE_FREE_LIST: case Page.TYPE_FREE_LIST:
writer.println("-- page " + page + ": free list " + (last ? "(last)" : "")); writer.println("-- page " + page + ": free list " + (last ? "(last)" : ""));
free += dumpPageFreeList(writer, s, pageSize, page, pageCount); free += dumpPageFreeList(writer, s, pageSize, page, pageCount);
...@@ -1031,7 +1033,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1031,7 +1033,7 @@ public class Recover extends Tool implements DataHandler {
} }
} }
private void dumpPageBtreeNode(PrintWriter writer, DataPage s) { private void dumpPageBtreeNode(PrintWriter writer, DataPage s, boolean positionOnly) {
int entryCount = s.readShortInt(); int entryCount = s.readShortInt();
int rowCount = s.readInt(); int rowCount = s.readInt();
int[] children = new int[entryCount + 1]; int[] children = new int[entryCount + 1];
...@@ -1046,12 +1048,16 @@ public class Recover extends Tool implements DataHandler { ...@@ -1046,12 +1048,16 @@ public class Recover extends Tool implements DataHandler {
s.setPos(off); s.setPos(off);
int pos = s.readInt(); int pos = s.readInt();
Value data; Value data;
if (positionOnly) {
data = ValueInt.get(pos);
} else {
try { try {
data = s.readValue(); data = s.readValue();
} catch (Throwable e) { } catch (Throwable e) {
writeDataError(writer, "exception " + e, s.getBytes(), blockCount); writeDataError(writer, "exception " + e, s.getBytes(), blockCount);
continue; continue;
} }
}
writer.println("-- [" + i + "] child: " + children[i] + " pos: " + pos + " data: " + data); writer.println("-- [" + i + "] child: " + children[i] + " pos: " + pos + " data: " + data);
} }
writer.println("-- [" + entryCount + "] child: " + children[entryCount] + " rowCount: " + rowCount); writer.println("-- [" + entryCount + "] child: " + children[entryCount] + " rowCount: " + rowCount);
...@@ -1084,8 +1090,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1084,8 +1090,7 @@ public class Recover extends Tool implements DataHandler {
return free; return free;
} }
private void dumpPageBtreeLeaf(PrintWriter writer, DataPage s) { private void dumpPageBtreeLeaf(PrintWriter writer, DataPage s, int entryCount, boolean positionOnly) {
int entryCount = s.readShortInt();
int[] offsets = new int[entryCount]; int[] offsets = new int[entryCount];
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
offsets[i] = s.readShortInt(); offsets[i] = s.readShortInt();
...@@ -1095,12 +1100,16 @@ public class Recover extends Tool implements DataHandler { ...@@ -1095,12 +1100,16 @@ public class Recover extends Tool implements DataHandler {
s.setPos(off); s.setPos(off);
int pos = s.readInt(); int pos = s.readInt();
Value data; Value data;
if (positionOnly) {
data = ValueInt.get(pos);
} else {
try { try {
data = s.readValue(); data = s.readValue();
} catch (Throwable e) { } catch (Throwable e) {
writeDataError(writer, "exception " + e, s.getBytes(), blockCount); writeDataError(writer, "exception " + e, s.getBytes(), blockCount);
continue; continue;
} }
}
writer.println("-- [" + i + "] pos: " + pos + " data: " + data); writer.println("-- [" + i + "] pos: " + pos + " data: " + data);
} }
} }
......
...@@ -7,13 +7,11 @@ ...@@ -7,13 +7,11 @@
package org.h2.test.synth; package org.h2.test.synth;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement; 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.Random; import java.util.Random;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
...@@ -92,7 +90,7 @@ public class TestBtreeIndex extends TestBase { ...@@ -92,7 +90,7 @@ public class TestBtreeIndex extends TestBase {
} }
String prefix = buff.toString(); String prefix = buff.toString();
DeleteDbFiles.execute(baseDir, null, true); DeleteDbFiles.execute(baseDir, null, true);
Connection conn = DriverManager.getConnection("jdbc:h2:" + baseDir + "/index", "sa", "sa"); Connection conn = getConnection("index");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("CREATE TABLE a(text VARCHAR PRIMARY KEY)"); stat.execute("CREATE TABLE a(text VARCHAR PRIMARY KEY)");
PreparedStatement prepInsert = conn.prepareStatement("INSERT INTO a VALUES(?)"); PreparedStatement prepInsert = conn.prepareStatement("INSERT INTO a VALUES(?)");
...@@ -119,8 +117,7 @@ public class TestBtreeIndex extends TestBase { ...@@ -119,8 +117,7 @@ public class TestBtreeIndex extends TestBase {
prepDeleteAllButOne.setString(1, prefix + y); prepDeleteAllButOne.setString(1, prefix + y);
int deleted = prepDeleteAllButOne.executeUpdate(); int deleted = prepDeleteAllButOne.executeUpdate();
if (deleted < count - 1) { if (deleted < count - 1) {
System.out.println("ERROR deleted:" + deleted); printError(seed, "deleted:" + deleted);
System.out.println("new TestBtreeIndex().");
} }
count -= deleted; count -= deleted;
} catch (SQLException e) { } catch (SQLException e) {
...@@ -132,8 +129,7 @@ public class TestBtreeIndex extends TestBase { ...@@ -132,8 +129,7 @@ public class TestBtreeIndex extends TestBase {
prepDelete.setString(1, prefix + y); prepDelete.setString(1, prefix + y);
int deleted = prepDelete.executeUpdate(); int deleted = prepDelete.executeUpdate();
if (deleted > 1) { if (deleted > 1) {
System.out.println("ERROR deleted:" + deleted); printError(seed, "deleted:" + deleted);
System.out.println("seed: " + seed);
} }
count -= deleted; count -= deleted;
} catch (SQLException e) { } catch (SQLException e) {
...@@ -143,21 +139,33 @@ public class TestBtreeIndex extends TestBase { ...@@ -143,21 +139,33 @@ public class TestBtreeIndex extends TestBase {
} }
} }
} }
ResultSet rs = conn.createStatement().executeQuery("SELECT text FROM a ORDER BY text"); int testCount;
int testCount = 0; testCount = 0;
while (rs.next()) { ResultSet rs = stat.executeQuery("SELECT text FROM a ORDER BY text");
ResultSet rs2 = conn.createStatement().executeQuery("SELECT text FROM a ORDER BY 'x' || text");
testCount = 0;
while (rs.next() && rs2.next()) {
if (!rs.getString(1).equals(rs2.getString(1))) {
fail("" + testCount);
}
testCount++; testCount++;
} }
assertFalse(rs.next());
assertFalse(rs2.next());
if (testCount != count) { if (testCount != count) {
System.out.println("ERROR count:" + count + " testCount:" + testCount); printError(seed, "count:" + count + " testCount:" + testCount);
System.out.println("seed: " + seed);
} }
rs = conn.createStatement().executeQuery("SELECT text, count(*) FROM a GROUP BY text HAVING COUNT(*)>1"); rs = stat.executeQuery("SELECT text, count(*) FROM a GROUP BY text HAVING COUNT(*)>1");
if (rs.next()) { if (rs.next()) {
System.out.println("ERROR"); printError(seed, "testCount:" + testCount);
System.out.println("seed: " + seed);
} }
conn.close(); conn.close();
} }
private void printError(int seed, String message) {
TestBase.logError("new TestBtreeIndex().init(test).testCase(" +
seed + "); // " + message, null);
fail(message);
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论