UserSqlHighStat.java
2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package io.mycat.statistic.stat;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.locks.ReentrantLock;
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
import io.mycat.statistic.SQLRecord;
public class UserSqlHighStat {
private static final int CAPACITY_SIZE = 1024;
private Map<String,SqlFrequency> sqlFrequencyMap = new ConcurrentHashMap<>();
private ReentrantLock lock = new ReentrantLock();
private SqlParser sqlParser = new SqlParser();
public void addSql(String sql, long executeTime,long startTime, long endTime ){
String newSql = this.sqlParser.mergeSql(sql);
SqlFrequency frequency = this.sqlFrequencyMap.get(newSql);
if ( frequency == null) {
//防止新建的时候的并发问题,只有新建的时候有锁
if(lock.tryLock()){
try{
frequency = new SqlFrequency();
frequency.setSql( newSql );
} finally {
lock.unlock();
}
} else{
while(frequency == null){
frequency = this.sqlFrequencyMap.get(newSql);
}
}
}
frequency.setLastTime( endTime );
frequency.incCount();
//TODO 目前setExecuteTime方法由于弃用锁,所以某些参数不准确,为了性能,放弃这些参数的准确性。下一步期待更多优化
frequency.setExecuteTime(executeTime);
this.sqlFrequencyMap.put(newSql, frequency);
}
/**
* 获取 SQL 访问频率
*/
public List<SqlFrequency> getSqlFrequency(boolean isClear) {
List<SqlFrequency> list = new ArrayList<>(this.sqlFrequencyMap.values());
if(isClear){
clearSqlFrequency();
}
return list;
}
private void clearSqlFrequency() {
sqlFrequencyMap.clear();
}
public void recycle() {
if(sqlFrequencyMap.size() > CAPACITY_SIZE){
Map<String,SqlFrequency> sqlFrequencyMap2 = new ConcurrentHashMap<>();
SortedSet<SqlFrequency> sqlFrequencySortedSet = new TreeSet<>(this.sqlFrequencyMap.values());
List<SqlFrequency> keyList = new ArrayList<SqlFrequency>(sqlFrequencySortedSet);
int i = 0;
for(SqlFrequency key : keyList){
if(i == CAPACITY_SIZE) {
break;
}
sqlFrequencyMap2.put(key.getSql(),key);
i++;
}
sqlFrequencyMap = sqlFrequencyMap2;
}
}
private static class SqlParser {
public String fixSql(String sql) {
if ( sql != null) {
return sql.replace("\n", " ");
}
return sql;
}
public String mergeSql(String sql) {
String newSql = ParameterizedOutputVisitorUtils.parameterize(sql, "mysql");
return fixSql( newSql );
}
}
}