@@ -254,6 +254,122 @@ func (o *MonitorHistoryOps) GetMonitorHistoriesByServerAndMonitor(serverID, moni
254254 return histories , nil
255255}
256256
257+ // GetMonitorHistoriesByServerAndMonitorOptimized 高效查询特定服务器和监控器的历史记录
258+ func (o * MonitorHistoryOps ) GetMonitorHistoriesByServerAndMonitorOptimized (serverID , monitorID uint64 , startTime , endTime time.Time , limit int ) ([]* model.MonitorHistory , error ) {
259+ var histories []* model.MonitorHistory
260+
261+ // 关键优化:使用更精确的key前缀,减少扫描范围
262+ // BadgerDB中的key格式通常是 "monitor_history:timestamp:serverid:monitorid" 或类似格式
263+ // 我们需要找到最优的扫描策略
264+
265+ err := o .db .db .View (func (txn * badger.Txn ) error {
266+ opts := badger .DefaultIteratorOptions
267+ opts .PrefetchValues = false // 先不预取值,只扫描key
268+ opts .PrefetchSize = 1000
269+ it := txn .NewIterator (opts )
270+ defer it .Close ()
271+
272+ prefix := "monitor_history:"
273+ count := 0
274+
275+ // 第一阶段:快速扫描key,过滤出匹配的记录
276+ var matchingKeys [][]byte
277+
278+ for it .Seek ([]byte (prefix )); it .ValidForPrefix ([]byte (prefix )) && count < limit * 2 ; it .Next () {
279+ item := it .Item ()
280+ key := item .Key ()
281+
282+ // 快速检查:先获取值来判断是否匹配条件
283+ err := item .Value (func (val []byte ) error {
284+ // 快速解析:只解析必要的字段
285+ var quickCheck struct {
286+ ServerID uint64 `json:"ServerID"`
287+ MonitorID uint64 `json:"MonitorID"`
288+ CreatedAt time.Time `json:"CreatedAt"`
289+ }
290+
291+ if err := json .Unmarshal (val , & quickCheck ); err != nil {
292+ return nil // 跳过无效记录
293+ }
294+
295+ // 快速过滤
296+ if quickCheck .ServerID == serverID &&
297+ quickCheck .MonitorID == monitorID &&
298+ quickCheck .CreatedAt .After (startTime ) &&
299+ quickCheck .CreatedAt .Before (endTime ) {
300+ // 复制key以避免BadgerDB的内存重用问题
301+ keyCopy := make ([]byte , len (key ))
302+ copy (keyCopy , key )
303+ matchingKeys = append (matchingKeys , keyCopy )
304+ count ++
305+ }
306+
307+ return nil
308+ })
309+
310+ if err != nil {
311+ return err
312+ }
313+ }
314+
315+ // 第二阶段:只处理匹配的记录,按时间排序
316+ type recordWithTime struct {
317+ history * model.MonitorHistory
318+ time time.Time
319+ }
320+
321+ var records []recordWithTime
322+
323+ for _ , key := range matchingKeys {
324+ item , err := txn .Get (key )
325+ if err != nil {
326+ continue
327+ }
328+
329+ err = item .Value (func (val []byte ) error {
330+ var history model.MonitorHistory
331+ if err := json .Unmarshal (val , & history ); err != nil {
332+ return nil
333+ }
334+
335+ records = append (records , recordWithTime {
336+ history : & history ,
337+ time : history .CreatedAt ,
338+ })
339+
340+ return nil
341+ })
342+
343+ if err != nil {
344+ return err
345+ }
346+ }
347+
348+ // 按时间排序(最新的在前)
349+ sort .Slice (records , func (i , j int ) bool {
350+ return records [i ].time .After (records [j ].time )
351+ })
352+
353+ // 限制结果数量
354+ maxResults := limit
355+ if len (records ) < maxResults {
356+ maxResults = len (records )
357+ }
358+
359+ for i := 0 ; i < maxResults ; i ++ {
360+ histories = append (histories , records [i ].history )
361+ }
362+
363+ return nil
364+ })
365+
366+ if err != nil {
367+ return nil , fmt .Errorf ("failed to query monitor histories optimized: %w" , err )
368+ }
369+
370+ return histories , nil
371+ }
372+
257373// CleanupOldMonitorHistories removes monitor histories older than maxAge
258374func (o * MonitorHistoryOps ) CleanupOldMonitorHistories (maxAge time.Duration ) (int , error ) {
259375 // Get all monitor IDs
0 commit comments