提交 47fee83f authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #617 from h2database/reindex_opt

Replace TreeSet with PriorityQueue in MVSecondaryIndex re-build
......@@ -10,7 +10,8 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import java.util.PriorityQueue;
import java.util.Queue;
import org.h2.api.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.Session;
......@@ -37,16 +38,14 @@ import org.h2.value.ValueNull;
/**
* A table stored in a MVStore.
*/
public class MVSecondaryIndex extends BaseIndex implements MVIndex {
public final class MVSecondaryIndex extends BaseIndex implements MVIndex {
/**
* The multi-value table.
*/
final MVTable mvTable;
private final MVTable mvTable;
private final int keyColumns;
private final String mapName;
private TransactionMap<Value, Value> dataMap;
private final TransactionMap<Value,Value> dataMap;
public MVSecondaryIndex(Database db, MVTable table, int id, String indexName,
IndexColumn[] columns, IndexType indexType) {
......@@ -58,7 +57,7 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
// always store the row key in the map key,
// even for unique indexes, as some of the index columns could be null
keyColumns = columns.length + 1;
mapName = "index." + getId();
String mapName = "index." + getId();
int[] sortTypes = new int[keyColumns];
for (int i = 0; i < columns.length; i++) {
sortTypes[i] = columns[i].sortType;
......@@ -77,84 +76,91 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
@Override
public void addRowsToBuffer(List<Row> rows, String bufferName) {
MVMap<Value, Value> map = openMap(bufferName);
MVMap<ValueArray, Value> map = openMap(bufferName);
for (Row row : rows) {
ValueArray key = convertToKey(row);
map.put(key, ValueNull.INSTANCE);
}
}
private static final class Source {
private final Iterator<ValueArray> iterator;
private ValueArray currentRowData;
public Source(Iterator<ValueArray> iterator) {
this.iterator = iterator;
this.currentRowData = iterator.next();
}
public boolean hasNext() {
boolean result = iterator.hasNext();
if(result) {
currentRowData = iterator.next();
}
return result;
}
public ValueArray next() {
return currentRowData;
}
public static final class Comparator implements java.util.Comparator<Source> {
private final CompareMode compareMode;
public Comparator(CompareMode compareMode) {
this.compareMode = compareMode;
}
@Override
public void addBufferedRows(List<String> bufferNames) {
ArrayList<String> mapNames = New.arrayList(bufferNames);
final CompareMode compareMode = database.getCompareMode();
/**
* A source of values.
*/
class Source implements Comparable<Source> {
Value value;
Iterator<Value> next;
int sourceId;
@Override
public int compareTo(Source o) {
int comp = value.compareTo(o.value, compareMode);
if (comp == 0) {
comp = sourceId - o.sourceId;
public int compare(Source one, Source two) {
return one.currentRowData.compareTo(two.currentRowData, compareMode);
}
return comp;
}
}
TreeSet<Source> sources = new TreeSet<>();
for (int i = 0; i < bufferNames.size(); i++) {
MVMap<Value, Value> map = openMap(bufferNames.get(i));
Iterator<Value> it = map.keyIterator(null);
if (it.hasNext()) {
Source s = new Source();
s.value = it.next();
s.next = it;
s.sourceId = i;
sources.add(s);
@Override
public void addBufferedRows(List<String> bufferNames) {
ArrayList<String> mapNames = New.arrayList(bufferNames);
CompareMode compareMode = database.getCompareMode();
int buffersCount = bufferNames.size();
Queue<Source> queue = new PriorityQueue<>(buffersCount, new Source.Comparator(compareMode));
for (String bufferName : bufferNames) {
Iterator<ValueArray> iter = openMap(bufferName).keyIterator(null);
if (iter.hasNext()) {
queue.add(new Source(iter));
}
}
try {
while (true) {
Source s = sources.first();
Value v = s.value;
while (!queue.isEmpty()) {
Source s = queue.remove();
ValueArray rowData = s.next();
if (indexType.isUnique()) {
Value[] array = ((ValueArray) v).getList();
Value[] array = rowData.getList();
// don't change the original value
array = array.clone();
array[keyColumns - 1] = ValueLong.get(Long.MIN_VALUE);
ValueArray unique = ValueArray.get(array);
SearchRow row = convertToSearchRow((ValueArray) v);
SearchRow row = convertToSearchRow(rowData);
checkUnique(row, dataMap, unique);
}
dataMap.putCommitted(v, ValueNull.INSTANCE);
dataMap.putCommitted(rowData, ValueNull.INSTANCE);
Iterator<Value> it = s.next;
if (!it.hasNext()) {
sources.remove(s);
if (sources.size() == 0) {
break;
}
} else {
Value nextValue = it.next();
sources.remove(s);
s.value = nextValue;
sources.add(s);
if (s.hasNext()) {
queue.offer(s);
}
}
} finally {
for (String tempMapName : mapNames) {
MVMap<Value, Value> map = openMap(tempMapName);
MVMap<ValueArray, Value> map = openMap(tempMapName);
map.getStore().removeMap(map);
}
}
}
private MVMap<Value, Value> openMap(String mapName) {
private MVMap<ValueArray, Value> openMap(String mapName) {
int[] sortTypes = new int[keyColumns];
for (int i = 0; i < indexColumns.length; i++) {
sortTypes[i] = indexColumns[i].sortType;
......@@ -163,9 +169,9 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
ValueDataType keyType = new ValueDataType(
database.getCompareMode(), database, sortTypes);
ValueDataType valueType = new ValueDataType(null, null, null);
MVMap.Builder<Value, Value> builder =
new MVMap.Builder<Value, Value>().keyType(keyType).valueType(valueType);
MVMap<Value, Value> map = database.getMvStore().
MVMap.Builder<ValueArray, Value> builder =
new MVMap.Builder<ValueArray, Value>().keyType(keyType).valueType(valueType);
MVMap<ValueArray, Value> map = database.getMvStore().
getStore().openMap(mapName, builder);
if (!keyType.equals(map.getKeyType())) {
throw DbException.throwInternalError("Incompatible key type");
......@@ -332,7 +338,7 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
* @param key the index key
* @return the row
*/
SearchRow convertToSearchRow(ValueArray key) {
private SearchRow convertToSearchRow(ValueArray key) {
Value[] array = key.getList();
SearchRow searchRow = mvTable.getTemplateRow();
searchRow.setKey((array[array.length - 1]).getLong());
......@@ -455,7 +461,7 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
* @param session the session
* @return the map
*/
TransactionMap<Value, Value> getMap(Session session) {
private TransactionMap<Value, Value> getMap(Session session) {
if (session == null) {
return dataMap;
}
......@@ -466,7 +472,7 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
/**
* A cursor.
*/
class MVStoreCursor implements Cursor {
final class MVStoreCursor implements Cursor {
private final Session session;
private final Iterator<Value> it;
......@@ -475,7 +481,7 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
private SearchRow searchRow;
private Row row;
public MVStoreCursor(Session session, Iterator<Value> it, SearchRow last) {
private MVStoreCursor(Session session, Iterator<Value> it, SearchRow last) {
this.session = session;
this.it = it;
this.last = last;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论