[英]Optimize number for SQL queries
我使用此代码生成包含数据的图表:
@GetMapping("/terminals")
public ResponseEntity<Map<String, List<TopTerminalsDTO>>> getTopTerminals(
@RequestParam(value = "start_date", required = true) String start_date,
@RequestParam(value = "end_date", required = true) String end_date) {
final List<PaymentTransactionsDailyFacts> list = dashboardService.findTop_Terminals(start_dateTime, end_dateTime);
final Collector<PaymentTransactionsDailyFacts, List<TopTerminalsDTO>, List<TopTerminalsDTO>> terminalsCollector = Collector
.of(ArrayList::new, (terminals, p) -> terminals.add(mapper.toTopTerminalsDTO(p)),
(accumulator, terminals) -> {
accumulator.addAll(terminals);
return accumulator;
});
final Map<String, List<TopTerminalsDTO>> final_map = list.stream().filter(p -> p.getTerminal_id() != null)
.collect(Collectors.groupingBy(p -> getTerminalName(p.getTerminal_id()), terminalsCollector));
return ResponseEntity.ok(final_map);
}
private String getTerminalName(Integer id) {
Optional<Terminals> obj = terminalService.findById(id);
return obj.map(Terminals::getName).orElse("");
}
但我注意到getTerminalName
被调用超过10次以从数字转换名称。 你知道我如何通过一些优化减少通话次数吗?
修改findTop_Terminals
和PaymentTransactionsDailyFacts
以包含名称(使用SQL LEFT JOIN
子句)。
或者,扫描列表中的所有终端ID,然后调用List<Terminals> list = terminalService.findByIds(idList);
使用SQL IN
子句获取所有终端的方法。
注意:注意限制多少?
标记可以在SQL语句中。
然后构建Map<Integer, String>
映射终端id到name,并用映射查找替换getTerminalName
方法。
听起来像是临时缓存的情况,仅限于此请求,或者如果终端名称足够稳定,则可能更长。
显然,像幕后的ehCache这样的东西很适合这种情况,但我经常会受到一些缓存的策略诱惑,特别是如果我不想让缓存的值超出这个直接请求的话。
例如:
TerminalNameCache cache = new TerminalNameCache();
final Map<String, List<TopTerminalsDTO>> final_map = list.stream()
.filter(p -> p.getTerminal_id() != null)
.collect(Collectors.groupingBy(
p -> cache.getTerminalName(p.getTerminal_id()),
terminalsCollector));
然后, TerminalNameCache
只是父Controller类中的内部类。 这是为了允许它从问题中调用现有的private String getTerminalName(Integer id)
方法(如下面的ParentControllerClass
所示):
private class TerminalNameCache {
private final Map<Integer, String> cache = new ConcurrentHashMap<>();
private String getTerminalName(Integer id) {
return cache.computeIfAbsent(id,
id2 -> ParentControllerClass.this.getTerminalName(id2));
}
}
如果这看起来像是一种模式,那么将缓存重构为更可重用的东西是值得的。 例如,这可以基于缓存对泛型函数的调用:
public class CachedFunction<T, R> implements Function<T, R> {
private final Function<T, R> function;
private final Map<T, R> cache = new ConcurrentHashMap<>();
public CachedFunction(Function<T, R> function) {
this.function = function;
}
@Override
public R apply(T t) {
return cache.computeIfAbsent(t, t2 -> function.apply(t2));
}
}
然后将这样使用:
CachedFunction<Integer, String> cachedFunction = new CachedFunction<>(
id -> getTerminalName(id));
final Map<String, List<TopTerminalsDTO>> final_map = list.stream()
.filter(p -> p.getTerminal_id() != null)
.collect(Collectors.groupingBy(
p -> cachedFunction.apply(p.getTerminal_id()),
terminalsCollector));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.