Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ public void setSingleDevice() {
this.singleDevice = true;
}

public boolean isSingleDevice() {
return singleDevice;
}

public List<Binary[]> getObjectColumns() {
List<Binary[]> objectColumns = new ArrayList<>();
for (int i = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertRowsNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertTabletNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.RelationalDeleteDataNode;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.RelationalInsertTabletNode;
import org.apache.iotdb.db.schemaengine.schemaregion.utils.ResourceByPathUtils;
import org.apache.iotdb.db.service.metrics.WritingMetrics;
import org.apache.iotdb.db.storageengine.dataregion.DataRegion;
Expand Down Expand Up @@ -648,19 +649,8 @@ public void insertTablet(

ensureMemTable(infoForMetrics);
workMemTable.checkDataType(insertTabletNode);
Set<IDeviceID> alignedDeviceIds = new HashSet<>();
if (insertTabletNode.isAligned()) {
for (int[] range : rangeList) {
for (Pair<IDeviceID, Integer> deviceEndPosition :
insertTabletNode.splitByDevice(range[0], range[1])) {
alignedDeviceIds.add(deviceEndPosition.getLeft());
}
}
}
AlignedTVListRamCostSnapshot alignedRamCostSnapshot =
alignedDeviceIds.isEmpty()
? null
: new AlignedTVListRamCostSnapshot(workMemTable, alignedDeviceIds);
takeAlignedTVListRamCostSnapshot(workMemTable, insertTabletNode, rangeList);

long[] memIncrements =
scheduleMemoryBlock(insertTabletNode, rangeList, results, infoForMetrics);
Expand Down Expand Up @@ -1394,6 +1384,30 @@ private void reconcileAlignedTVListRamCost(
}
}

static AlignedTVListRamCostSnapshot takeAlignedTVListRamCostSnapshot(
IMemTable memTable, InsertTabletNode insertTabletNode, List<int[]> rangeList) {
if (!insertTabletNode.isAligned() || rangeList.isEmpty()) {
return null;
}

if (!(insertTabletNode instanceof RelationalInsertTabletNode)
|| ((RelationalInsertTabletNode) insertTabletNode).isSingleDevice()) {
return new AlignedTVListRamCostSnapshot(
memTable, insertTabletNode.getDeviceID(rangeList.get(0)[0]));
}

Set<IDeviceID> alignedDeviceIds = new HashSet<>();
for (int[] range : rangeList) {
for (Pair<IDeviceID, Integer> deviceEndPosition :
insertTabletNode.splitByDevice(range[0], range[1])) {
alignedDeviceIds.add(deviceEndPosition.getLeft());
}
}
return alignedDeviceIds.isEmpty()
? null
: new AlignedTVListRamCostSnapshot(memTable, alignedDeviceIds);
}

static final class AlignedTVListRamCostSnapshot {

private final IMemTable memTable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public abstract class AlignedTVList extends TVList {
private long materializedBitmapMemoryCost;
private long arrayMemCostWithoutPrimitiveArraysAndIndex;

// Data type list -> list of TVList, add 1 when expanded -> primitive array of basic type
// Data type list -> list of TVList, add 1 when expanded -> primitive array of basic type.
// A null primitive array means all existing rows in that block are null for the column.
// Index relation: columnIndex(dataTypeIndex) -> arrayIndex -> elementIndex
protected List<List<Object>> values;

Expand Down Expand Up @@ -261,7 +262,7 @@ public synchronized void putAlignedValue(long timestamp, Object[] value) {
markNullValue(i, arrayIndex, elementIndex);
continue;
}
Object valueArray = getOrCreateValueArray(i, arrayIndex);
Object valueArray = getOrCreateValueArray(i, arrayIndex, elementIndex);
switch (dataTypes.get(i)) {
case TEXT:
case BLOB:
Expand Down Expand Up @@ -406,37 +407,13 @@ private TsPrimitiveType getAlignedValueByValueIndex(
}

public void extendColumn(TSDataType dataType) {
if (bitMaps == null) {
List<List<BitMap>> localBitMaps = new ArrayList<>(values.size());
for (int i = 0; i < values.size(); i++) {
localBitMaps.add(null);
}
bitMaps = localBitMaps;
}
List<Object> columnValue = new ArrayList<>(timestamps.size());
List<BitMap> columnBitMaps = new ArrayList<>(timestamps.size());
for (int i = 0; i < timestamps.size(); i++) {
columnValue.add(null);
BitMap bitMap = BitMap.createBitMapDynamically(ARRAY_SIZE);
// The following code is for these 2 kinds of scenarios.

// Eg1: If rowCount=5 and ARRAY_SIZE=2, we need to supply 3 bitmaps for the extending column.
// The first 2 bitmaps should mark all bits to represent 4 nulls and the 3rd bitmap should
// mark
// the 1st bit to represent 1 null value.

// Eg2: If rowCount=4 and ARRAY_SIZE=2, we need to supply 2 bitmaps for the extending column.
// These 2 bitmaps should mark all bits to represent 4 nulls.
if (i == timestamps.size() - 1 && rowCount % ARRAY_SIZE != 0) {
bitMap.markRange(0, rowCount % ARRAY_SIZE);
} else {
bitMap.markAll();
}
columnBitMaps.add(bitMap);
}
materializedBitmapMemoryCost +=
(long) timestamps.size() * (bitmapReferenceRamCost() + bitmapRamCost());
this.bitMaps.add(columnBitMaps);
if (bitMaps != null) {
bitMaps.add(null);
}
this.values.add(columnValue);
this.dataTypes.add(dataType);
refreshArrayMemCostWithoutPrimitiveArrays();
Expand Down Expand Up @@ -722,28 +699,14 @@ public Pair<Integer, Boolean> delete(long lowerBound, long upperBound, int colum
}

public void deleteColumn(int columnIndex) {
if (bitMaps == null) {
List<List<BitMap>> localBitMaps = new ArrayList<>(dataTypes.size());
for (int j = 0; j < dataTypes.size(); j++) {
localBitMaps.add(null);
}
bitMaps = localBitMaps;
}
if (bitMaps.get(columnIndex) == null) {
List<BitMap> columnBitMaps = new ArrayList<>(values.get(columnIndex).size());
for (int i = 0; i < values.get(columnIndex).size(); i++) {
columnBitMaps.add(BitMap.createBitMapDynamically(ARRAY_SIZE));
}
bitMaps.set(columnIndex, columnBitMaps);
materializedBitmapMemoryCost +=
(long) columnBitMaps.size() * (bitmapReferenceRamCost() + bitmapRamCost());
List<Object> columnValues = values.get(columnIndex);
if (columnValues == null) {
return;
}
for (int i = 0; i < bitMaps.get(columnIndex).size(); i++) {
if (bitMaps.get(columnIndex).get(i) == null) {
bitMaps.get(columnIndex).set(i, BitMap.createBitMapDynamically(ARRAY_SIZE));
materializedBitmapMemoryCost += bitmapRamCost();
for (int arrayIndex = 0; arrayIndex < columnValues.size(); arrayIndex++) {
if (columnValues.get(arrayIndex) != null) {
getBitMap(columnIndex, arrayIndex).markAll();
}
bitMaps.get(columnIndex).get(i).markAll();
}
}

Expand Down Expand Up @@ -928,7 +891,7 @@ public synchronized void putAlignedValues(
}

private void markNullBitmapRange(
Object[] values,
Object[] inputValues,
BitMap[] bitMaps,
TSStatus[] results,
int idx,
Expand All @@ -942,9 +905,15 @@ private void markNullBitmapRange(
? buildResultBitMap(results, idx, elementIdx, len)
: null;

for (int j = 0; j < values.length; j++) {
for (int j = 0; j < inputValues.length; j++) {
// A null value array represents an entirely null block, so no bitmap is needed until the
// block receives its first non-null value.
if (values.get(j).get(arrayIndex) == null) {
continue;
}

/* Fast-path: column is entirely null */
if (values[j] == null) {
if (inputValues[j] == null) {
getBitMap(j, arrayIndex).markRange(elementIdx, len);
continue;
}
Expand All @@ -970,9 +939,11 @@ private static boolean containsFailedStatus(TSStatus[] results, int start, int l
return false;
}

private static boolean containsMarkedBit(BitMap bitMap, int start, int length) {
if (length <= 0) {
return false;
static boolean containsMarkedBit(BitMap bitMap, int start, int length) {
// Avoid materializing a byte-array copy on the common aligned-tablet path, which starts at
// offset 0 and can be inspected directly by BitMap.
if (start == 0) {
return length > 0 && !bitMap.isAllUnmarked(length);
}

byte[] bytes = bitMap.getByteArray();
Expand Down Expand Up @@ -1032,7 +1003,7 @@ private void arrayCopy(
if (value[i] == null || !containsNonNullValue(bitMaps, results, i, idx, remaining)) {
continue;
}
Object valueArray = getOrCreateValueArray(i, arrayIndex);
Object valueArray = getOrCreateValueArray(i, arrayIndex, elementIndex);
switch (dataTypes.get(i)) {
case TEXT:
case BLOB:
Expand Down Expand Up @@ -1096,14 +1067,17 @@ private static boolean containsNonNullValue(
return false;
}

private Object getOrCreateValueArray(int columnIndex, int arrayIndex) {
private Object getOrCreateValueArray(int columnIndex, int arrayIndex, int elementIndex) {
List<Object> columnValues = values.get(columnIndex);
Object valueArray = columnValues.get(arrayIndex);
if (valueArray == null) {
valueArray = getPrimitiveArraysByType(dataTypes.get(columnIndex));
columnValues.set(arrayIndex, valueArray);
materializedValueArrayCounts[columnIndex]++;
materializedValueArrayMemCost += valueListArrayMemCost(dataTypes.get(columnIndex));
if (elementIndex > 0) {
getBitMap(columnIndex, arrayIndex).markRange(0, elementIndex);
}
}
return valueArray;
}
Expand Down Expand Up @@ -1138,6 +1112,10 @@ private BitMap getBitMap(int columnIndex, int arrayIndex) {
}

private boolean markNullValue(int columnIndex, int arrayIndex, int elementIndex) {
List<Object> columnValues = values.get(columnIndex);
if (columnValues == null || columnValues.get(arrayIndex) == null) {
return false;
}
// mark the null value in the current bitmap
BitMap bitMap = getBitMap(columnIndex, arrayIndex);
if (bitMap.isMarked(elementIndex)) {
Expand Down Expand Up @@ -1779,60 +1757,55 @@ public BitMap getAllValueColDeletedMap() {
}

public BitMap getAllValueColDeletedMap(int rowCount) {
// row exists when any column value exists
if (bitMaps == null) {
if (rowCount <= 0) {
return null;
}

int blockCount = (rowCount + ARRAY_SIZE - 1) / ARRAY_SIZE;
// Preserve the dense fast path: one column without null blocks or bitmaps proves that every row
// has at least one value.
for (int columnIndex = 0; columnIndex < values.size(); columnIndex++) {
if (values.get(columnIndex) != null && bitMaps.get(columnIndex) == null) {
List<Object> columnValues = values.get(columnIndex);
if (columnValues == null) {
continue;
}
List<BitMap> columnBitMaps = bitMaps == null ? null : bitMaps.get(columnIndex);
boolean columnHasNoNull = true;
for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) {
if (columnValues.get(blockIndex) == null
|| (columnBitMaps != null && columnBitMaps.get(blockIndex) != null)) {
columnHasNoNull = false;
break;
}
}
if (columnHasNoNull) {
return null;
}
}

byte[] rowBitsArr = new byte[rowCount / Byte.SIZE + 1];
int bitsMapSize =
rowCount % ARRAY_SIZE == 0 ? rowCount / ARRAY_SIZE : rowCount / ARRAY_SIZE + 1;
boolean[] allNotNullArray = new boolean[bitsMapSize];
byte[] rowBitsArr = new byte[(rowCount + Byte.SIZE - 1) / Byte.SIZE];
Arrays.fill(rowBitsArr, (byte) 0xFF);
for (int columnIndex = 0; columnIndex < values.size(); columnIndex++) {
List<BitMap> columnBitMaps = bitMaps.get(columnIndex);
if (columnBitMaps == null) {
Arrays.fill(rowBitsArr, (byte) 0x00);
break;
} else if (values.get(columnIndex) != null) {
int row = 0;
boolean isEnd = true;
for (int i = 0; i < bitsMapSize; i++) {
if (allNotNullArray[i]) {
row += ARRAY_SIZE;
continue;
}

BitMap bitMap = columnBitMaps.get(i);
int index = row / Byte.SIZE;
int size = ((Math.min((rowCount - row), ARRAY_SIZE)) + 7) >>> 3;
row += ARRAY_SIZE;

if (bitMap == null) {
Arrays.fill(rowBitsArr, index, index + size, (byte) 0x00);
allNotNullArray[i] = true;
continue;
}

byte bits = (byte) 0X00;
byte[] bitMapBytes = bitMap.getByteArray();
for (int j = 0; j < size; j++) {
rowBitsArr[index] &= bitMapBytes[j];
bits |= rowBitsArr[index++];
isEnd = false;
}

allNotNullArray[i] = bits == (byte) 0;
for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) {
int row = blockIndex * ARRAY_SIZE;
int byteIndex = row / Byte.SIZE;
int byteCount = (Math.min(rowCount - row, ARRAY_SIZE) + Byte.SIZE - 1) / Byte.SIZE;
for (int columnIndex = 0; columnIndex < values.size(); columnIndex++) {
List<Object> columnValues = values.get(columnIndex);
if (columnValues == null || columnValues.get(blockIndex) == null) {
continue;
}

if (isEnd) {
List<BitMap> columnBitMaps = bitMaps == null ? null : bitMaps.get(columnIndex);
BitMap bitMap = columnBitMaps == null ? null : columnBitMaps.get(blockIndex);
if (bitMap == null) {
Arrays.fill(rowBitsArr, byteIndex, byteIndex + byteCount, (byte) 0x00);
break;
}

byte[] bitMapBytes = bitMap.getByteArray();
for (int i = 0; i < byteCount; i++) {
rowBitsArr[byteIndex + i] &= bitMapBytes[i];
}
}
}
return new BitMap(rowCount, rowBitsArr);
Expand Down Expand Up @@ -1861,19 +1834,9 @@ public int getAvgPointSizeOfLargestColumn() {

private int getColumnValueCnt(int columnIndex) {
int pointNum = 0;
if (bitMaps == null || bitMaps.get(columnIndex) == null) {
pointNum = rowCount;
} else {
for (int i = 0; i < rowCount; i++) {
int arrayIndex = i / ARRAY_SIZE;
if (bitMaps.get(columnIndex).get(arrayIndex) == null) {
pointNum++;
} else {
int elementIndex = i % ARRAY_SIZE;
if (!bitMaps.get(columnIndex).get(arrayIndex).isMarked(elementIndex)) {
pointNum++;
}
}
for (int i = 0; i < rowCount; i++) {
if (!isNullValue(i, columnIndex)) {
pointNum++;
}
}
return pointNum;
Expand Down
Loading
Loading