Skip to content

Commit a565a06

Browse files
authored
Added flags to mark whether a device has device descendants to optimize query like select xx from xxx.** (#17672)
* flag- * Fix * Address device descendant flag review comments
1 parent 958ce45 commit a565a06

17 files changed

Lines changed: 869 additions & 65 deletions

File tree

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,43 @@ private void applySubtreeMeasurementDelta(IMemMNode startNode, final long delta)
208208
}
209209
}
210210

211+
private IDeviceMNode<IMemMNode> setToEntityAndUpdateFlags(final IMemMNode node) {
212+
final boolean wasDevice = node.isDevice();
213+
final IDeviceMNode<IMemMNode> deviceMNode = store.setToEntity(node);
214+
if (!wasDevice) {
215+
markAncestorsHavingDeviceDescendant(node);
216+
}
217+
return deviceMNode;
218+
}
219+
220+
private void markAncestorsHavingDeviceDescendant(final IMemMNode deviceNode) {
221+
IMemMNode current = deviceNode.getParent();
222+
while (current != null && !current.hasDeviceDescendant()) {
223+
current.setHasDeviceDescendant(true);
224+
current = current.getParent();
225+
}
226+
}
227+
228+
private boolean hasDeviceDescendantInChildren(final IMemMNode node) {
229+
try (final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(node)) {
230+
while (iterator.hasNext()) {
231+
final IMemMNode child = iterator.next();
232+
if (child.isDevice() || child.hasDeviceDescendant()) {
233+
return true;
234+
}
235+
}
236+
return false;
237+
}
238+
}
239+
240+
private void refreshAncestorsHavingDeviceDescendant(IMemMNode startNode) {
241+
IMemMNode current = startNode;
242+
while (current != null) {
243+
current.setHasDeviceDescendant(hasDeviceDescendantInChildren(current));
244+
current = current.getParent();
245+
}
246+
}
247+
211248
private long getTemplateMeasurementCount(final int templateId) {
212249
final Template template = ClusterTemplateManager.getInstance().getTemplate(templateId);
213250
return template == null ? 0L : template.getMeasurementNumber();
@@ -316,7 +353,7 @@ public IMeasurementMNode<IMemMNode> createTimeSeries(
316353
if (device.isDevice()) {
317354
entityMNode = device.getAsDeviceMNode();
318355
} else {
319-
entityMNode = store.setToEntity(device);
356+
entityMNode = setToEntityAndUpdateFlags(device);
320357
}
321358

322359
// create a non-aligned time series
@@ -410,7 +447,7 @@ public List<IMeasurementMNode<IMemMNode>> createAlignedTimeSeries(
410447
if (device.isDevice()) {
411448
entityMNode = device.getAsDeviceMNode();
412449
} else {
413-
entityMNode = store.setToEntity(device);
450+
entityMNode = setToEntityAndUpdateFlags(device);
414451
entityMNode.setAligned(true);
415452
}
416453

@@ -658,14 +695,15 @@ public void deleteEmptyInternalMNode(final IDeviceMNode<IMemMNode> entityMNode)
658695
boolean hasMeasurement = false;
659696
boolean hasNonViewMeasurement = false;
660697
IMemMNode child;
661-
IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(curNode);
662-
while (iterator.hasNext()) {
663-
child = iterator.next();
664-
if (child.isMeasurement()) {
665-
hasMeasurement = true;
666-
if (!child.getAsMeasurementMNode().isLogicalView()) {
667-
hasNonViewMeasurement = true;
668-
break;
698+
try (final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(curNode)) {
699+
while (iterator.hasNext()) {
700+
child = iterator.next();
701+
if (child.isMeasurement()) {
702+
hasMeasurement = true;
703+
if (!child.getAsMeasurementMNode().isLogicalView()) {
704+
hasNonViewMeasurement = true;
705+
break;
706+
}
669707
}
670708
}
671709
}
@@ -674,6 +712,7 @@ public void deleteEmptyInternalMNode(final IDeviceMNode<IMemMNode> entityMNode)
674712
synchronized (this) {
675713
curNode = store.setToInternal(entityMNode);
676714
}
715+
refreshAncestorsHavingDeviceDescendant(curNode.getParent());
677716
} else if (!hasNonViewMeasurement) {
678717
// has some measurement but they are all logical view
679718
entityMNode.setAligned(null);
@@ -1034,7 +1073,7 @@ public void activateTemplate(final PartialPath activatePath, final Template temp
10341073
if (cur.isDevice()) {
10351074
entityMNode = cur.getAsDeviceMNode();
10361075
} else {
1037-
entityMNode = store.setToEntity(cur);
1076+
entityMNode = setToEntityAndUpdateFlags(cur);
10381077
}
10391078
}
10401079

@@ -1142,7 +1181,7 @@ public void activateTemplateWithoutCheck(
11421181
if (cur.isDevice()) {
11431182
entityMNode = cur.getAsDeviceMNode();
11441183
} else {
1145-
entityMNode = store.setToEntity(cur);
1184+
entityMNode = setToEntityAndUpdateFlags(cur);
11461185
}
11471186

11481187
if (!entityMNode.isAligned()) {
@@ -1197,14 +1236,21 @@ public void rebuildSubtreeMeasurementCount() {
11971236

11981237
private long rebuildSubtreeMeasurementCountFromNode(final IMemMNode node) {
11991238
long count = node.isMeasurement() ? 1L : 0L;
1200-
final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(node);
1201-
while (iterator.hasNext()) {
1202-
count += rebuildSubtreeMeasurementCountFromNode(iterator.next());
1239+
boolean hasDeviceDescendant = false;
1240+
try (final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(node)) {
1241+
while (iterator.hasNext()) {
1242+
final IMemMNode child = iterator.next();
1243+
count += rebuildSubtreeMeasurementCountFromNode(child);
1244+
if (child.isDevice() || child.hasDeviceDescendant()) {
1245+
hasDeviceDescendant = true;
1246+
}
1247+
}
12031248
}
12041249
if (node.isDevice() && node.getAsDeviceMNode().isUseTemplate()) {
12051250
count += getTemplateMeasurementCount(node.getAsDeviceMNode().getSchemaTemplateId());
12061251
}
12071252
node.setSubtreeMeasurementCount(count);
1253+
node.setHasDeviceDescendant(hasDeviceDescendant);
12081254
return count;
12091255
}
12101256

@@ -1787,7 +1833,7 @@ public IMeasurementMNode<IMemMNode> createLogicalView(
17871833
if (device.isDevice()) {
17881834
entityMNode = device.getAsDeviceMNode();
17891835
} else {
1790-
entityMNode = store.setToEntity(device);
1836+
entityMNode = setToEntityAndUpdateFlags(device);
17911837
// this parent has no measurement before. The leafName is his first child who is a logical
17921838
// view.
17931839
entityMNode.setAligned(null);
@@ -1928,7 +1974,7 @@ public void createOrUpdateTableDevice(
19281974
(TableDeviceInfo<IMemMNode>) entityMNode.getDeviceInfo();
19291975
attributeUpdater.accept(deviceInfo.getAttributePointer());
19301976
} else {
1931-
entityMNode = store.setToEntity(cur);
1977+
entityMNode = setToEntityAndUpdateFlags(cur);
19321978
final TableDeviceInfo<IMemMNode> deviceInfo = new TableDeviceInfo<>();
19331979
deviceInfo.setAttributePointer(attributePointerGetter.getAsInt());
19341980
entityMNode.getAsInternalMNode().setDeviceInfo(deviceInfo);
@@ -2046,6 +2092,7 @@ protected Void collectMNode(final IMemMNode node) {
20462092
collector.traverse();
20472093
}
20482094
databaseMNode.deleteChild(tableName);
2095+
refreshAncestorsHavingDeviceDescendant(databaseMNode);
20492096
regionStatistics.resetTableDevice(tableName);
20502097
store.releaseMemory(memoryReleased.get());
20512098
return true;

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/IMemMNode.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,33 @@
1919
package org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode;
2020

2121
import org.apache.iotdb.commons.schema.node.IMNode;
22+
import org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.basic.BasicMNode;
2223

2324
public interface IMemMNode extends IMNode<IMemMNode> {
2425

26+
BasicMNode getBasicMNode();
27+
2528
/**
2629
* The count of measurement nodes contained in the subtree rooted at this node. The counter is
2730
* maintained in memory only.
2831
*/
29-
long getSubtreeMeasurementCount();
32+
default long getSubtreeMeasurementCount() {
33+
return getBasicMNode().getSubtreeMeasurementCount();
34+
}
35+
36+
default void setSubtreeMeasurementCount(final long subtreeMeasurementCount) {
37+
getBasicMNode().setSubtreeMeasurementCount(subtreeMeasurementCount);
38+
}
39+
40+
/**
41+
* Whether there is any device node in the subtree rooted at this node, excluding the node itself.
42+
* This flag is maintained in memory only.
43+
*/
44+
default boolean hasDeviceDescendant() {
45+
return getBasicMNode().hasDeviceDescendant();
46+
}
3047

31-
void setSubtreeMeasurementCount(long subtreeMeasurementCount);
48+
default void setHasDeviceDescendant(final boolean hasDeviceDescendant) {
49+
getBasicMNode().setHasDeviceDescendant(hasDeviceDescendant);
50+
}
3251
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/basic/BasicMNode.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public class BasicMNode implements IMemMNode {
5050
/** Cached count of measurements in this node's subtree, rebuilt on restart. */
5151
private long subtreeMeasurementCount = 0L;
5252

53+
/** Cached flag showing whether there is any device in the subtree below this node. */
54+
private boolean hasDeviceDescendant = false;
55+
5356
/** from root to this node, only be set when used once for InternalMNode */
5457
private String fullPath;
5558

@@ -59,6 +62,11 @@ public BasicMNode(IMemMNode parent, String name) {
5962
this.basicMNodeInfo = new BasicMNodeInfo(name);
6063
}
6164

65+
@Override
66+
public BasicMNode getBasicMNode() {
67+
return this;
68+
}
69+
6270
@Override
6371
public String getName() {
6472
return basicMNodeInfo.getName();
@@ -113,6 +121,16 @@ public void setSubtreeMeasurementCount(final long subtreeMeasurementCount) {
113121
this.subtreeMeasurementCount = subtreeMeasurementCount;
114122
}
115123

124+
@Override
125+
public boolean hasDeviceDescendant() {
126+
return hasDeviceDescendant;
127+
}
128+
129+
@Override
130+
public void setHasDeviceDescendant(final boolean hasDeviceDescendant) {
131+
this.hasDeviceDescendant = hasDeviceDescendant;
132+
}
133+
116134
@Override
117135
public PartialPath getPartialPath() {
118136
final List<String> detachedPath = new ArrayList<>();
@@ -240,6 +258,7 @@ public <R, C> R accept(final MNodeVisitor<R, C> visitor, final C context) {
240258
* <li>parent reference, 8B
241259
* <li>fullPath reference, 8B
242260
* <li>subtreeMeasurementCount, 8B
261+
* <li>hasDeviceDescendant, 1B
243262
* </ol>
244263
* <li>MapEntry in parent
245264
* <ol>
@@ -251,7 +270,7 @@ public <R, C> R accept(final MNodeVisitor<R, C> visitor, final C context) {
251270
*/
252271
@Override
253272
public int estimateSize() {
254-
return 8 + 8 + 8 + 8 + 8 + 8 + 8 + 28 + basicMNodeInfo.estimateSize();
273+
return 8 + 8 + 8 + 8 + 8 + 1 + 8 + 8 + 28 + basicMNodeInfo.estimateSize();
255274
}
256275

257276
@Override

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/impl/AboveDatabaseMNode.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,4 @@ public AboveDatabaseMNode(IMemMNode parent, String name) {
3333
public IMemMNode getAsMNode() {
3434
return this;
3535
}
36-
37-
@Override
38-
public long getSubtreeMeasurementCount() {
39-
return basicMNode.getSubtreeMeasurementCount();
40-
}
41-
42-
@Override
43-
public void setSubtreeMeasurementCount(long subtreeMeasurementCount) {
44-
basicMNode.setSubtreeMeasurementCount(subtreeMeasurementCount);
45-
}
4636
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/impl/DatabaseMNode.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,4 @@ public IDeviceInfo<IMemMNode> getDeviceInfo() {
4545
public void setDeviceInfo(IDeviceInfo<IMemMNode> deviceInfo) {
4646
basicMNode.setDeviceInfo(deviceInfo);
4747
}
48-
49-
@Override
50-
public long getSubtreeMeasurementCount() {
51-
return basicMNode.getSubtreeMeasurementCount();
52-
}
53-
54-
@Override
55-
public void setSubtreeMeasurementCount(long subtreeMeasurementCount) {
56-
basicMNode.setSubtreeMeasurementCount(subtreeMeasurementCount);
57-
}
5848
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/impl/MeasurementMNode.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,4 @@ public IMNodeContainer<IMemMNode> getChildren() {
5252
public final boolean isLogicalView() {
5353
return false;
5454
}
55-
56-
@Override
57-
public long getSubtreeMeasurementCount() {
58-
return basicMNode.getSubtreeMeasurementCount();
59-
}
60-
61-
@Override
62-
public void setSubtreeMeasurementCount(long subtreeMeasurementCount) {
63-
basicMNode.setSubtreeMeasurementCount(subtreeMeasurementCount);
64-
}
6555
}

0 commit comments

Comments
 (0)