前言
关于Select查询请求结果涉及到的一些数据结构
Series定义type Series struct {
// Name is the measurement name.
Name string
// Tags for the series.
Tags Tags
id uint64
}
type Tags struct {
id string
m map[string]string}Series其实就是measurement和tags的组合,tags是tag key和tag value的map.这个Tags的id是如何产生的呢,其实就是对tag key和tag value编码到[]byte: tagkey1\0tagkey2\0...\tagvalue1\0tagvalue2\0...,具体实现定义在query/point.go中的encodeTags
Row定义type Row struct {
Time int64 // Series contains the series metadata for this row.
Series Series // Values contains the values within the current row.
Values []interface{}
}Row表示查询结果集中的每一行, 其中的Values表示是返回的Fields的集合
IteratorbufFloatIterator定义type bufFloatIterator struct {
itr FloatIterator
buf *FloatPoint
}
相当于c里面的链表元素,itr指向下一个元素的指针,buf表示当前元素,即FloatPoint类型的链表的迭代器.看一下FloatPoint定义type FloatPoint struct {
Name string
Tags Tags
Time int64
Value float64
Aux []interface{} // Total number of points that were combined into this point from an aggregate.
// If this is zero, the point is not the result of an aggregate function.
Aggregated uint32
Nil bool}
定义在query/point.gen.go中, 表示一条field为float类型的数据Next实现func (itr *bufFloatIterator) Next() (*FloatPoint, error) {
buf := itr.buf if buf != nil {
itr.buf = nil
return buf, nil
} return itr.itr.Next()
}
当前Iterator的值不为空,就返回当前的buf, 当前的值为空,就返回itr.itr.Next(),即指向的下一个元素unread: iterator回退操作func (itr *bufFloatIterator) unread(v *FloatPoint) { itr.buf = v }floatMergeIterator组合了多个floatIterator
我们来看下定义type floatMergeIterator struct {
inputs []FloatIterator
heap *floatMergeHeap
init bool
closed bool
mu sync.RWMutex // Current iterator and window.
curr *floatMergeHeapItem
window struct {
name string
tags string
startTime int64
endTime int64
}
}
因为要作merge, 这里需要对其管理的所有Interator元素作排序,这里用到了golang的container/heap作堆排, 大小根堆不太清楚了大家自行google吧。
因为要用golang的container/heap来管理,需要实现下面规定的接口,type Interface interface {
sort.Interface
Push(x interface{}) // add x as element Len()
Pop() interface{} // remove and return element Len() - 1.}
floatMergeIterator定义中的floatMergeHeap即实现了上面的接口,我们主要来看一下比较函数的实现,比较的其实就是FloatPointfunc (h *floatMergeHeap) Less(i, j int) bool {
x, err := h.items[i].itr.peek() if err != nil { return true
}
y, err := h.items[j].itr.peek() if err != nil { return false
} if h.opt.Ascending { if x.Name != y.Name { return x.Name
} else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { return xTags.ID()
}
} else { if x.Name != y.Name { return x.Name > y.Name
} else if xTags, yTags := x.Tags.Subset(h.opt.Dimensions), y.Tags.Subset(h.opt.Dimensions); xTags.ID() != yTags.ID() { return xTags.ID() > yTags.ID()
}
}
xt, _ := h.opt.Window(x.Time)
yt, _ := h.opt.Window(y.Time) if h.opt.Ascending { return xt
} return xt > yt
}
比较的优先级先是FloatPoint的measurement名,然后是tagset id, 最后是time,将这个比较函数我们就可以知道.看一下结构:
float_merge_iterator.png
Next函数的实现func (itr *floatMergeIterator) Next() (*FloatPoint, error) {
itr.mu.RLock()
defer itr.mu.RUnlock() if itr.closed { return nil, nil
}
// 堆排的heap数据结构并不会一开始就构造,而是在首次遍历时初始化构造
if !itr.init {
items := itr.heap.items
itr.heap.items = make([]*floatMergeHeapItem, 0, len(items)) for _, item := range items { if p, err := item.itr.peek(); err != nil { return nil, err
} else if p == nil { continue
}
itr.heap.items = append(itr.heap.items, item)
}
heap.Init(itr.heap)
itr.init = true
} for { // Retrieve the next iterator if we don't have one.
if itr.curr == nil { if len(itr.heap.items) == 0 { r