Performance Improvement
This commit is contained in:
parent
41cbdd154e
commit
52e1bef1d2
@ -48,10 +48,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
@ -67,7 +64,7 @@ import static org.thingsboard.server.dao.timeseries.SqlTsPartitionDate.EPOCH_STA
|
|||||||
public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEntity> implements TimeseriesDao {
|
public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEntity> implements TimeseriesDao {
|
||||||
|
|
||||||
private final ConcurrentMap<String, Integer> tsKvDictionaryMap = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, Integer> tsKvDictionaryMap = new ConcurrentHashMap<>();
|
||||||
private final Set<PsqlPartition> partitions = ConcurrentHashMap.newKeySet();
|
private final Map<Long, PsqlPartition> partitions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final ReentrantLock tsCreationLock = new ReentrantLock();
|
private static final ReentrantLock tsCreationLock = new ReentrantLock();
|
||||||
private static final ReentrantLock partitionCreationLock = new ReentrantLock();
|
private static final ReentrantLock partitionCreationLock = new ReentrantLock();
|
||||||
@ -82,6 +79,7 @@ public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEnt
|
|||||||
private PsqlPartitioningRepository partitioningRepository;
|
private PsqlPartitioningRepository partitioningRepository;
|
||||||
|
|
||||||
private SqlTsPartitionDate tsFormat;
|
private SqlTsPartitionDate tsFormat;
|
||||||
|
private PsqlPartition indefinitePartition;
|
||||||
|
|
||||||
@Value("${sql.ts_key_value_partitioning}")
|
@Value("${sql.ts_key_value_partitioning}")
|
||||||
private String partitioning;
|
private String partitioning;
|
||||||
@ -92,6 +90,10 @@ public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEnt
|
|||||||
Optional<SqlTsPartitionDate> partition = SqlTsPartitionDate.parse(partitioning);
|
Optional<SqlTsPartitionDate> partition = SqlTsPartitionDate.parse(partitioning);
|
||||||
if (partition.isPresent()) {
|
if (partition.isPresent()) {
|
||||||
tsFormat = partition.get();
|
tsFormat = partition.get();
|
||||||
|
if (tsFormat.equals(SqlTsPartitionDate.INDEFINITE)) {
|
||||||
|
indefinitePartition = new PsqlPartition(toMills(EPOCH_START), Long.MAX_VALUE, tsFormat.getPattern());
|
||||||
|
savePartition(indefinitePartition);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn("Incorrect configuration of partitioning {}", partitioning);
|
log.warn("Incorrect configuration of partitioning {}", partitioning);
|
||||||
throw new RuntimeException("Failed to parse partitioning property: " + partitioning + "!");
|
throw new RuntimeException("Failed to parse partitioning property: " + partitioning + "!");
|
||||||
@ -116,23 +118,22 @@ public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEnt
|
|||||||
entity.setLongValue(tsKvEntry.getLongValue().orElse(null));
|
entity.setLongValue(tsKvEntry.getLongValue().orElse(null));
|
||||||
entity.setBooleanValue(tsKvEntry.getBooleanValue().orElse(null));
|
entity.setBooleanValue(tsKvEntry.getBooleanValue().orElse(null));
|
||||||
PsqlPartition psqlPartition = toPartition(tsKvEntry.getTs());
|
PsqlPartition psqlPartition = toPartition(tsKvEntry.getTs());
|
||||||
savePartition(psqlPartition);
|
|
||||||
log.trace("Saving entity: {}", entity);
|
log.trace("Saving entity: {}", entity);
|
||||||
return tsQueue.add(new EntityContainer(entity, psqlPartition.getPartitionDate()));
|
return tsQueue.add(new EntityContainer(entity, psqlPartition.getPartitionDate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> remove(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
public ListenableFuture<Void> remove(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
||||||
return service.submit(() -> {
|
return service.submit(() -> {
|
||||||
String strKey = query.getKey();
|
String strKey = query.getKey();
|
||||||
Integer keyId = getOrSaveKeyId(strKey);
|
Integer keyId = getOrSaveKeyId(strKey);
|
||||||
tsKvRepository.delete(
|
tsKvRepository.delete(
|
||||||
entityId.getId(),
|
entityId.getId(),
|
||||||
keyId,
|
keyId,
|
||||||
query.getStartTs(),
|
query.getStartTs(),
|
||||||
query.getEndTs());
|
query.getEndTs());
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -286,13 +287,13 @@ public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void savePartition(PsqlPartition psqlPartition) {
|
private void savePartition(PsqlPartition psqlPartition) {
|
||||||
if (!partitions.contains(psqlPartition)) {
|
if (!partitions.containsKey(psqlPartition.getStart())) {
|
||||||
partitionCreationLock.lock();
|
partitionCreationLock.lock();
|
||||||
try {
|
try {
|
||||||
log.trace("Saving partition: {}", psqlPartition);
|
log.trace("Saving partition: {}", psqlPartition);
|
||||||
partitioningRepository.save(psqlPartition);
|
partitioningRepository.save(psqlPartition);
|
||||||
log.trace("Adding partition to Set: {}", psqlPartition);
|
log.trace("Adding partition to Set: {}", psqlPartition);
|
||||||
partitions.add(psqlPartition);
|
partitions.put(psqlPartition.getStart(), psqlPartition);
|
||||||
} finally {
|
} finally {
|
||||||
partitionCreationLock.unlock();
|
partitionCreationLock.unlock();
|
||||||
}
|
}
|
||||||
@ -300,17 +301,28 @@ public class JpaPsqlTimeseriesDao extends AbstractSimpleSqlTimeseriesDao<TsKvEnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PsqlPartition toPartition(long ts) {
|
private PsqlPartition toPartition(long ts) {
|
||||||
if (tsFormat.getTruncateUnit().equals(SqlTsPartitionDate.INDEFINITE.getTruncateUnit())) {
|
if (tsFormat.equals(SqlTsPartitionDate.INDEFINITE)) {
|
||||||
return new PsqlPartition(toMills(EPOCH_START), Long.MAX_VALUE, tsFormat.getPattern());
|
return indefinitePartition;
|
||||||
} else {
|
} else {
|
||||||
LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC);
|
LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC);
|
||||||
LocalDateTime localDateTimeStart = tsFormat.trancateTo(time);
|
LocalDateTime localDateTimeStart = tsFormat.trancateTo(time);
|
||||||
LocalDateTime localDateTimeEnd = tsFormat.plusTo(localDateTimeStart);
|
long partitionStartTs = toMills(localDateTimeStart);
|
||||||
ZonedDateTime zonedDateTime = localDateTimeStart.atZone(ZoneOffset.UTC);
|
PsqlPartition partition = partitions.get(partitionStartTs);
|
||||||
String partitionDate = zonedDateTime.format(DateTimeFormatter.ofPattern(tsFormat.getPattern()));
|
if (partition != null) {
|
||||||
return new PsqlPartition(toMills(localDateTimeStart), toMills(localDateTimeEnd), partitionDate);
|
return partition;
|
||||||
|
} else {
|
||||||
|
LocalDateTime localDateTimeEnd = tsFormat.plusTo(localDateTimeStart);
|
||||||
|
long partitionEndTs = toMills(localDateTimeEnd);
|
||||||
|
ZonedDateTime zonedDateTime = localDateTimeStart.atZone(ZoneOffset.UTC);
|
||||||
|
String partitionDate = zonedDateTime.format(DateTimeFormatter.ofPattern(tsFormat.getPattern()));
|
||||||
|
partition = new PsqlPartition(partitionStartTs, partitionEndTs, partitionDate);
|
||||||
|
savePartition(partition);
|
||||||
|
return partition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long toMills(LocalDateTime time) { return time.toInstant(ZoneOffset.UTC).toEpochMilli(); }
|
private static long toMills(LocalDateTime time) {
|
||||||
|
return time.toInstant(ZoneOffset.UTC).toEpochMilli();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user