提交 35d966ee authored 作者: Thomas Mueller's avatar Thomas Mueller

The database file was growing after deleting many rows, and after large update operations.

上级 f10983aa
...@@ -43,6 +43,7 @@ public class Storage { ...@@ -43,6 +43,7 @@ public class Storage {
private DiskFile file; private DiskFile file;
private int recordCount; private int recordCount;
private RecordReader reader; private RecordReader reader;
private int freeCount;
private IntArray freeList = new IntArray(); private IntArray freeList = new IntArray();
private IntArray pages = new IntArray(); private IntArray pages = new IntArray();
private int id; private int id;
...@@ -220,16 +221,44 @@ public class Storage { ...@@ -220,16 +221,44 @@ public class Storage {
return true; return true;
} }
} }
private void refillFreeList() {
if (freeList.size() != 0 || freeCount == 0) {
return;
}
BitField used = file.getUsed();
for (int i = 0; i < pages.size(); i++) {
int p = pages.get(i);
int block = DiskFile.BLOCKS_PER_PAGE * p;
for (int j = 0; j < DiskFile.BLOCKS_PER_PAGE; j++) {
if (!used.get(block)) {
if (freeList.size() < FREE_LIST_SIZE) {
freeList.add(block);
} else {
return;
}
}
block++;
}
}
// if we came here, all free records must be in the list
// otherwise it would have returned early
if (SysProperties.CHECK && freeCount > freeList.size()) {
throw Message.getInternalError("freeCount expected " + freeList.size() + ", got: " + freeCount);
}
freeCount = freeList.size();
}
private int allocate(int blockCount) throws SQLException { private int allocate(int blockCount) throws SQLException {
refillFreeList();
if (freeList.size() > 0) { if (freeList.size() > 0) {
synchronized (database) { synchronized (database) {
BitField used = file.getUsed(); BitField used = file.getUsed();
for (int i = 0; i < freeList.size(); i++) { for (int i = 0; i < freeList.size(); i++) {
int px = freeList.get(i); int px = freeList.get(i);
if (used.get(px)) { if (used.get(px)) {
// sometime there may stay some entries in the freeList // sometimes some entries in the freeList
// that are not free (free 2, free 1, allocate 1+2) // are not free (free 2, free 1, allocate 1+2)
// these entries are removed right here // these entries are removed right here
freeList.remove(i--); freeList.remove(i--);
} else { } else {
...@@ -237,6 +266,7 @@ public class Storage { ...@@ -237,6 +266,7 @@ public class Storage {
int pos = px; int pos = px;
freeList.remove(i); freeList.remove(i);
file.setUsed(pos, blockCount); file.setUsed(pos, blockCount);
freeCount -= blockCount;
return pos; return pos;
} }
} }
...@@ -245,6 +275,7 @@ public class Storage { ...@@ -245,6 +275,7 @@ public class Storage {
} }
int pos = file.allocate(this, blockCount); int pos = file.allocate(this, blockCount);
file.setUsed(pos, blockCount); file.setUsed(pos, blockCount);
freeCount -= blockCount;
return pos; return pos;
} }
...@@ -259,6 +290,7 @@ public class Storage { ...@@ -259,6 +290,7 @@ public class Storage {
if (freeList.size() < FREE_LIST_SIZE) { if (freeList.size() < FREE_LIST_SIZE) {
freeList.add(pos); freeList.add(pos);
} }
freeCount += blockCount;
} }
// private int allocateBest(int start, int blocks) { // private int allocateBest(int start, int blocks) {
...@@ -299,6 +331,7 @@ public class Storage { ...@@ -299,6 +331,7 @@ public class Storage {
*/ */
public void truncate(Session session) throws SQLException { public void truncate(Session session) throws SQLException {
freeList = new IntArray(); freeList = new IntArray();
freeCount = 0;
recordCount = 0; recordCount = 0;
file.truncateStorage(session, this, pages); file.truncateStorage(session, this, pages);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论