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

MVStore: tool to quickly compact a store.

上级 a14c7148
...@@ -1280,7 +1280,12 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1280,7 +1280,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
CursorPos pos = new CursorPos(target, 0, parent); CursorPos pos = new CursorPos(target, 0, parent);
for (int i = 0; i < target.getChildPageCount(); i++) { for (int i = 0; i < target.getChildPageCount(); i++) {
pos.index = i; pos.index = i;
copy(source.getChildPage(i), pos); long p = source.getChildPagePos(i);
if (p != 0) {
// p == 0 means no child
// (for example the last entry of an r-tree node)
copy(source.getChildPage(i), pos);
}
} }
target = pos.page; target = pos.page;
} }
......
...@@ -33,6 +33,10 @@ public class MVStoreTool { ...@@ -33,6 +33,10 @@ public class MVStoreTool {
* <td>Dump the contends of the file</td></tr> * <td>Dump the contends of the file</td></tr>
* <tr><td>[-info &lt;fileName&gt;]</td> * <tr><td>[-info &lt;fileName&gt;]</td>
* <td>Get summary information about a file</td></tr> * <td>Get summary information about a file</td></tr>
* <tr><td>[-compact &lt;fileName&gt;]</td>
* <td>Compact a store</td></tr>
* <tr><td>[-compress &lt;fileName&gt;]</td>
* <td>Compact a store with compression enabled</td></tr>
* </table> * </table>
* *
* @param args the command line arguments * @param args the command line arguments
...@@ -274,10 +278,12 @@ public class MVStoreTool { ...@@ -274,10 +278,12 @@ public class MVStoreTool {
} }
pw.printf("Created: %s\n", formatTimestamp(fileCreated)); pw.printf("Created: %s\n", formatTimestamp(fileCreated));
pw.printf("File length: %d\n", fileLength); pw.printf("File length: %d\n", fileLength);
pw.printf("Excluding the last chunk\n");
pw.printf("Chunk length: %d\n", chunkLength); pw.printf("Chunk length: %d\n", chunkLength);
pw.printf("Chunk count: %d\n", chunks.size()); pw.printf("Chunk count: %d\n", chunks.size());
pw.printf("Used space: %d%%\n", 100 * chunkLength / fileLength); pw.printf("Used space: %d%%\n", 100 * chunkLength / fileLength);
pw.printf("Chunk fill rate: %d%%\n", 100 * maxLengthLive / maxLength); pw.printf("Chunk fill rate: %d%%\n", maxLength == 0 ? 100 :
100 * maxLengthLive / maxLength);
for (Entry<Integer, Chunk> e : chunks.entrySet()) { for (Entry<Integer, Chunk> e : chunks.entrySet()) {
Chunk c = e.getValue(); Chunk c = e.getValue();
long created = fileCreated + c.time; long created = fileCreated + c.time;
......
...@@ -6,10 +6,13 @@ ...@@ -6,10 +6,13 @@
package org.h2.test.store; package org.h2.test.store;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Random;
import org.h2.mvstore.MVMap; import org.h2.mvstore.MVMap;
import org.h2.mvstore.MVStore; import org.h2.mvstore.MVStore;
import org.h2.mvstore.MVStoreTool; import org.h2.mvstore.MVStoreTool;
import org.h2.mvstore.rtree.MVRTreeMap;
import org.h2.mvstore.rtree.SpatialKey;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -32,17 +35,17 @@ public class TestMVStoreTool extends TestBase { ...@@ -32,17 +35,17 @@ public class TestMVStoreTool extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
testCompress(); testCompact();
} }
private void testCompress() { private void testCompact() {
String fileName = getBaseDir() + "/testCompress.h3"; String fileName = getBaseDir() + "/testCompact.h3";
FileUtils.createDirectories(getBaseDir()); FileUtils.createDirectories(getBaseDir());
FileUtils.delete(fileName); FileUtils.delete(fileName);
// store with a very small page size, to make sure // store with a very small page size, to make sure
// there are many leaf pages // there are many leaf pages
MVStore s = new MVStore.Builder(). MVStore s = new MVStore.Builder().
pageSplitSize(100). pageSplitSize(1000).
fileName(fileName).autoCommitDisabled().open(); fileName(fileName).autoCommitDisabled().open();
MVMap<Integer, String> map = s.openMap("data"); MVMap<Integer, String> map = s.openMap("data");
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
...@@ -51,14 +54,28 @@ public class TestMVStoreTool extends TestBase { ...@@ -51,14 +54,28 @@ public class TestMVStoreTool extends TestBase {
s.commit(); s.commit();
} }
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 20; i++) {
map = s.openMap("data" + i); map = s.openMap("data" + i);
for (int j = 0; j < i * i; j++) { for (int j = 0; j < i * i; j++) {
map.put(j, "Hello World " + j * 10); map.put(j, "Hello World " + j * 10);
} }
s.commit(); s.commit();
} }
MVRTreeMap<String> rTreeMap = s.openMap("rtree", new MVRTreeMap.Builder<String>());
Random r = new Random(1);
for (int i = 0; i < 10; i++) {
float x = r.nextFloat();
float y = r.nextFloat();
float width = r.nextFloat() / 10;
float height = r.nextFloat() / 10;
SpatialKey k = new SpatialKey(i, x, x + width, y, y + height);
rTreeMap.put(k, "Hello World " + i * 10);
if (i % 3 == 0) {
s.commit();
}
}
s.close(); s.close();
MVStoreTool.compact(fileName, fileName + ".new", false); MVStoreTool.compact(fileName, fileName + ".new", false);
MVStoreTool.compact(fileName, fileName + ".new.compress", true); MVStoreTool.compact(fileName, fileName + ".new.compress", true);
MVStore s1 = new MVStore.Builder(). MVStore s1 = new MVStore.Builder().
...@@ -78,12 +95,25 @@ public class TestMVStoreTool extends TestBase { ...@@ -78,12 +95,25 @@ public class TestMVStoreTool extends TestBase {
private void assertEquals(MVStore a, MVStore b) { private void assertEquals(MVStore a, MVStore b) {
assertEquals(a.getMapNames().size(), b.getMapNames().size()); assertEquals(a.getMapNames().size(), b.getMapNames().size());
for (String mapName : a.getMapNames()) { for (String mapName : a.getMapNames()) {
MVMap<?, ?> ma = a.openMap(mapName); if (mapName.startsWith("rtree")) {
MVMap<?, ?> mb = a.openMap(mapName); MVRTreeMap<String> ma = a.openMap(
assertEquals(ma.sizeAsLong(), mb.sizeAsLong()); mapName, new MVRTreeMap.Builder<String>());
for (Entry<?, ?> e : ma.entrySet()) { MVRTreeMap<String> mb = b.openMap(
Object x = mb.get(e.getKey()); mapName, new MVRTreeMap.Builder<String>());
assertEquals(e.getValue().toString(), x.toString()); assertEquals(ma.sizeAsLong(), mb.sizeAsLong());
for (Entry<SpatialKey, String> e : ma.entrySet()) {
Object x = mb.get(e.getKey());
assertEquals(e.getValue().toString(), x.toString());
}
} else {
MVMap<?, ?> ma = a.openMap(mapName);
MVMap<?, ?> mb = a.openMap(mapName);
assertEquals(ma.sizeAsLong(), mb.sizeAsLong());
for (Entry<?, ?> e : ma.entrySet()) {
Object x = mb.get(e.getKey());
assertEquals(e.getValue().toString(), x.toString());
}
} }
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论