Skip to content

Commit

Permalink
[optimize](table stat) Reduce lock when get table statistics (#39807)
Browse files Browse the repository at this point in the history
## Proposed changes

Issue Number: this pr will pick part of #35457 to reduce the potential
of dead lock with following example:

时间点 | create table线程1 | create table线程2 | table stat线程 | truncate线程
-- | -- | -- | -- | --
t1 | add table1 read lock |   |   |  
t2 |   | add table2 read lock |   |  
t3 |   |   | try add table1 write lock,blocked |  
t4 |   |   |   | try add table2 write lock,blocked
t5 | try add table2 read lock,Due to a thread attempting to add the
table2 write lock earlier, it was forced to queue up |   |   |  
t6 |   | try add table1 read lock,Due to a thread attempting to add the
table1 write lock earlier, it was forced to queue up |   |  

This deadlock situation usually occurs when it is a fair lock. So we
should optimize the read lock.

This PR places the updates of table statistics(such as data size/replica
count) in the Table Stats Thread to be done on a scheduled basis, so
that there is no need to add a read lock when obtaining table
statistics.

<!--Describe your changes.-->
  • Loading branch information
xy720 authored Aug 28, 2024
1 parent 299d221 commit 367d264
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,8 @@ public int compare(Table t1, Table t2) {
OlapTable olapTable = (OlapTable) table;
long tableSize = 0;
long replicaCount = 0;
olapTable.readLock();
try {
tableSize = olapTable.getDataSize();
replicaCount = olapTable.getReplicaCount();
} finally {
olapTable.readUnlock();
}
tableSize = olapTable.getDataSize();
replicaCount = olapTable.getReplicaCount();
//|TableName|Size|ReplicaCount|
List<Object> row = Arrays.asList(table.getName(), tableSize, replicaCount);
totalRowsObject.add(row);
Expand Down
52 changes: 23 additions & 29 deletions fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -231,48 +231,42 @@ public void setDbProperties(DatabaseProperty dbProperties) {

public long getUsedDataQuotaWithLock() {
long usedDataQuota = 0;
List<Table> tables = new ArrayList<>();
readLock();
try {
for (Table table : this.idToTable.values()) {
if (table.getType() != TableType.OLAP) {
continue;
}

OlapTable olapTable = (OlapTable) table;
olapTable.readLock();
try {
usedDataQuota = usedDataQuota + olapTable.getDataSize();
} finally {
olapTable.readUnlock();
}
}
return usedDataQuota;
tables.addAll(this.idToTable.values());
} finally {
readUnlock();
}
for (Table table : tables) {
if (table.getType() != TableType.OLAP) {
continue;
}

OlapTable olapTable = (OlapTable) table;
usedDataQuota = usedDataQuota + olapTable.getDataSize();
}
return usedDataQuota;
}

public long getReplicaCountWithLock() {
long usedReplicaCount = 0;
List<Table> tables = new ArrayList<>();
readLock();
try {
long usedReplicaCount = 0;
for (Table table : this.idToTable.values()) {
if (table.getType() != TableType.OLAP) {
continue;
}

OlapTable olapTable = (OlapTable) table;
olapTable.readLock();
try {
usedReplicaCount = usedReplicaCount + olapTable.getReplicaCount();
} finally {
olapTable.readUnlock();
}
}
return usedReplicaCount;
tables.addAll(this.idToTable.values());
} finally {
readUnlock();
}
for (Table table : tables) {
if (table.getType() != TableType.OLAP) {
continue;
}

OlapTable olapTable = (OlapTable) table;
usedReplicaCount = usedReplicaCount + olapTable.getReplicaCount();
}
return usedReplicaCount;
}

public long getReplicaQuotaLeftWithLock() {
Expand Down
79 changes: 59 additions & 20 deletions fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
import java.util.Set;
import java.util.stream.Collectors;

import lombok.Getter;

/**
* Internal representation of tableFamilyGroup-related metadata. A OlaptableFamilyGroup contains several tableFamily.
* Note: when you add a new olap table property, you should modify TableProperty class
Expand Down Expand Up @@ -148,6 +150,8 @@ public enum OlapTableState {

private TableProperty tableProperty;

private volatile Statistics statistics = new Statistics();

public OlapTable() {
// for persist
super(TableType.OLAP);
Expand Down Expand Up @@ -1393,26 +1397,6 @@ public Partition replacePartition(Partition newPartition) {
return oldPartition;
}

public long getDataSize(boolean singleReplica) {
long dataSize = 0;
for (Partition partition : getAllPartitions()) {
dataSize += partition.getDataSize(singleReplica);
}
return dataSize;
}

public long getDataSize() {
return getDataSize(false);
}

public long getReplicaCount() {
long replicaCount = 0;
for (Partition partition : getAllPartitions()) {
replicaCount += partition.getReplicaCount();
}
return replicaCount;
}

public void checkStableAndNormal(String clusterName) throws DdlException {
if (state != OlapTableState.NORMAL) {
throw new DdlException("Table[" + name + "]'s state is not NORMAL. "
Expand Down Expand Up @@ -1995,4 +1979,59 @@ public boolean isDupKeysOrMergeOnWrite() {
|| (getKeysType() == KeysType.UNIQUE_KEYS
&& getEnableUniqueKeyMergeOnWrite());
}

public void setStatistics(Statistics statistics) {
this.statistics = statistics;
}

public static class Statistics {
@Getter
private String dbName;
@Getter
private String tableName;

@Getter
private Long dataSize; // single replica data size
@Getter
private Long totalReplicaDataSize;

@Getter
private Long replicaCount;

public Statistics() {
this.dbName = null;
this.tableName = null;

this.dataSize = 0L;
this.totalReplicaDataSize = 0L;

this.replicaCount = 0L;
}

public Statistics(String dbName, String tableName,
Long dataSize, Long totalReplicaDataSize, Long replicaCount) {
this.dbName = dbName;
this.tableName = tableName;

this.dataSize = dataSize;
this.totalReplicaDataSize = totalReplicaDataSize;

this.replicaCount = replicaCount;
}
}

public long getDataSize() {
return getDataSize(false);
}

public long getDataSize(boolean singleReplica) {
if (singleReplica) {
return statistics.getDataSize();
}
return statistics.getTotalReplicaDataSize();
}

public long getReplicaCount() {
return statistics.getReplicaCount();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ protected void runAfterCatalogReady() {
continue;
}
OlapTable olapTable = (OlapTable) table;
long tableDataSize = 0L;
long tableTotalReplicaDataSize = 0L;
long tableReplicaCount = 0L;
if (!table.writeLockIfExist()) {
continue;
}
Expand All @@ -103,18 +106,29 @@ protected void runAfterCatalogReady() {
for (MaterializedIndex index : partition.getMaterializedIndices(IndexExtState.VISIBLE)) {
long indexRowCount = 0L;
for (Tablet tablet : index.getTablets()) {
long tabletDataSize = 0L;
long tabletRowCount = 0L;
for (Replica replica : tablet.getReplicas()) {
if (replica.checkVersionCatchUp(version, false)
&& replica.getRowCount() > tabletRowCount) {
tabletRowCount = replica.getRowCount();
}

if (replica.getDataSize() > tabletDataSize) {
tabletDataSize = replica.getDataSize();
}
tableTotalReplicaDataSize += replica.getDataSize();
tableReplicaCount++;
}
tableDataSize += tabletDataSize;
indexRowCount += tabletRowCount;
} // end for tablets
index.setRowCount(indexRowCount);
} // end for indices
} // end for partitions

olapTable.setStatistics(new OlapTable.Statistics(db.getFullName(), table.getName(),
tableDataSize, tableTotalReplicaDataSize, tableReplicaCount));
LOG.debug("finished to set row num for table: {} in database: {}",
table.getName(), db.getFullName());
} finally {
Expand Down

0 comments on commit 367d264

Please sign in to comment.