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

Reuse space after deleting or updating many rows in a b-tree index.

上级 046a5037
......@@ -18,9 +18,12 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>When using Turkish as the default locale, sometimes columns could not be accessed
using the lowercase column alias or name. This affects locales where String.toUpper("a...z") does not
result in "A...Z", which is so far only Turkish, where "i".toUpperCase() is "I" with dot above.
<ul><li>When deleting or updating many rows in a table, the space in the index
file was not re-used in the default mode (persistent database, b-tree index,
LOG=1). This caused the index file to grow over time. Workarounds were to
delete and re-created the index file, alter the table (add a remove a column),
or use LOG=2. To disable the change, set the system property
h2.reuseSpaceBtreeIndex to false.
</li><li>Identifiers with a digit and then a dollar sign didn't work. Example: A1$B.
</li><li>MS SQL Server compatibility: support for linked tables with
NVARCHAR, NCHAR, NCLOB, and LONGNVARCHAR.
......
......@@ -513,6 +513,12 @@ public class SysProperties {
*/
public static final int REUSE_SPACE_AFTER = getIntSetting("h2.reuseSpaceAfter", 32);
/**
* System property <code>h2.reuseSpaceBtreeIndex</code> (default: true).<br />
* Reuse space after deleting or updating many rows in a b-tree index.
*/
public static final boolean REUSE_SPACE_BTREE_INDEX = getBooleanSetting("h2.reuseSpaceBtreeIndex", true);
/**
* System property <code>h2.reuseSpaceQuickly</code> (default: true).<br />
* Reuse space in database files quickly.
......
......@@ -142,7 +142,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
* @param p the page to update
*/
void updatePage(Session session, Record p) throws SQLException {
if (database.getLogIndexChanges()) {
if (SysProperties.REUSE_SPACE_BTREE_INDEX || database.getLogIndexChanges()) {
storage.addRecord(session, p, p.getPos());
} else {
storage.updateRecord(session, p);
......@@ -156,7 +156,7 @@ public class BtreeIndex extends BaseIndex implements RecordReader {
* @param p the page to remove
*/
void deletePage(Session session, Record p) throws SQLException {
if (database.getLogIndexChanges()) {
if (SysProperties.REUSE_SPACE_BTREE_INDEX || database.getLogIndexChanges()) {
storage.removeRecord(session, p.getPos());
}
}
......
......@@ -424,10 +424,13 @@ public class Storage {
}
private void checkOnePage() throws SQLException {
pageCheckIndex = (pageCheckIndex + 1) % pages.size();
int page = pages.get(pageCheckIndex);
if (file.isPageFree(page) && file.getPageOwner(page) == id) {
file.freePage(page);
int size = pages.size();
if (size > 0) {
pageCheckIndex = (pageCheckIndex + 1) % size;
int page = pages.get(pageCheckIndex);
if (file.isPageFree(page) && file.getPageOwner(page) == id) {
file.freePage(page);
}
}
}
......
......@@ -679,7 +679,31 @@ public class Recover extends Tool implements DataHandler {
} else {
pageOwners[page] = storageId;
}
writer.println("// [" + block + "] page:" + page + " blocks:" + blockCount + " storage:" + storageId);
String data = "";
int type = s.readByte();
int len;
switch (type) {
case 'L':
boolean pos = s.readByte() == 'P';
len = s.readInt();
data = "leaf(" + len + ")";
if (pos) {
data += " pos";
}
break;
case 'N':
len = s.readInt();
data = "node ";
for (int i = 0; i < len; i++) {
data += "[" + s.readInt() + "]";
}
break;
case 'H':
int rootPos = s.readInt();
data = "root [" + rootPos + "]";
break;
}
writer.println("// [" + block + "] page:" + page + " blocks:" + blockCount + " storage:" + storageId + " " + data);
}
writer.close();
} catch (Throwable e) {
......
......@@ -286,16 +286,12 @@ java org.h2.test.TestAll timer
System.setProperty("h2.maxMemoryRowsDistinct", "128");
System.setProperty("h2.check2", "true");
// 2009-05-15: 25 test fail with page store (first loop)
// 2009-05-15: 25 tests fail with page store (first loop)
// 2009-05-18: 18 tests fail with page store (first loop)
// System.setProperty("h2.pageStore", "true");
/*
index grows:
runscript from '~/Desktop/merge.sql';
create table test(id int, name varchar, primary key(id, name));
@LOOP 10000 merge into test(id, name) values(?, 'test' || ?);
BaseIndex or TableData should have its own compareMode
(default is: Database.compareMode when created).
standard: COLLATE for each column (MySQL, SQL Server)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论