query_agg.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. package core
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "math/big"
  6. "slices"
  7. "git.ycl.pub/yl32940/TsDB2/DB/core/index"
  8. "git.ycl.pub/yl32940/TsDB2/DB/core/page"
  9. "git.ycl.pub/yl32940/TsDB2/DB/core/types"
  10. )
  11. // orderKeySpec 预解析的排序键: 排序列不存在于表中时在构建阶段就被丢掉,
  12. // 比较阶段不再做任何字段查找。
  13. type orderKeySpec struct {
  14. field string
  15. ft types.FieldType
  16. desc bool
  17. }
  18. // buildOrderSpecs 把 OrderBy 解析成排序键规格 (字段名 + 列类型 + 方向)。
  19. func (q *Query) buildOrderSpecs() []orderKeySpec {
  20. specs := make([]orderKeySpec, 0, len(q.orderBys))
  21. for _, ob := range q.orderBys {
  22. idx := q.table.findFieldIndex(ob.Field)
  23. if idx < 0 {
  24. continue
  25. }
  26. specs = append(specs, orderKeySpec{
  27. field: ob.Field,
  28. ft: q.table.Field[idx].FieldType,
  29. desc: ob.Descending,
  30. })
  31. }
  32. return specs
  33. }
  34. // compareRowsForOrderBy 按 OrderBy 规则比较两行, 返回 -1/0/1。
  35. // 0 表示"所有排序列都无法区分"(字段缺失), 由调用方用稳定排序保持原顺序。
  36. //
  37. // 保留给外部调用方; 查询内部排序走 sortResults (decoration 每行只提取一次键)。
  38. func (q *Query) compareRowsForOrderBy(a, b []types.FieldValue) int {
  39. return compareRowsBySpecs(a, b, q.buildOrderSpecs())
  40. }
  41. // compareRowsBySpecs 按预解析规格比较两行 (每行先经 lookupFieldValue 取值)。
  42. func compareRowsBySpecs(a, b []types.FieldValue, specs []orderKeySpec) int {
  43. for _, s := range specs {
  44. vi, _ := lookupFieldValue(a, []byte(s.field))
  45. vj, _ := lookupFieldValue(b, []byte(s.field))
  46. if vi == nil || vj == nil {
  47. continue
  48. }
  49. cmp := compareFieldValues(vi, vj, s.ft)
  50. if cmp == 0 {
  51. continue
  52. }
  53. if s.desc {
  54. return -cmp
  55. }
  56. return cmp
  57. }
  58. return 0
  59. }
  60. // ======================== 排序 ========================
  61. // sortResults 内存排序: decoration 阶段每行按名提取一次排序键, 键随行进数组
  62. // (排序会重排元素, 平行键数组会错位), 比较阶段零查找。
  63. // 行集合可能因 NULL 跳列而宽窄不一, 键按名进行、缺失用 nil 占位,
  64. // 语义与旧比较器完全一致。
  65. func (q *Query) sortResults(results [][]types.FieldValue) {
  66. specs := q.buildOrderSpecs()
  67. if len(specs) == 0 {
  68. return
  69. }
  70. dec := make([]struct {
  71. row []types.FieldValue
  72. keys []interface{}
  73. }, len(results))
  74. for i := range results {
  75. k := make([]interface{}, len(specs))
  76. for j, s := range specs {
  77. k[j], _ = lookupFieldValue(results[i], []byte(s.field))
  78. }
  79. dec[i] = struct {
  80. row []types.FieldValue
  81. keys []interface{}
  82. }{results[i], k}
  83. }
  84. slices.SortStableFunc(dec, func(a, b struct {
  85. row []types.FieldValue
  86. keys []interface{}
  87. }) int {
  88. return compareKeys(a.keys, b.keys, specs)
  89. })
  90. for i := range dec {
  91. results[i] = dec[i].row
  92. }
  93. }
  94. // compareKeys 比较两行预提取的排序键。
  95. func compareKeys(ka, kb []interface{}, specs []orderKeySpec) int {
  96. for j, s := range specs {
  97. vi, vj := ka[j], kb[j]
  98. if vi == nil || vj == nil {
  99. continue
  100. }
  101. cmp := compareFieldValues(vi, vj, s.ft)
  102. if cmp == 0 {
  103. continue
  104. }
  105. if s.desc {
  106. return -cmp
  107. }
  108. return cmp
  109. }
  110. return 0
  111. }
  112. // ======================== 流式 top-k (ORDER BY + LIMIT) ========================
  113. // topkItem 堆内元素: 行 + 预提取排序键 + 输入序号。
  114. // 序号做相等键的决胜 —— 弹出顺序与 slices.SortStableFunc 完全一致 (稳定)。
  115. type topkItem struct {
  116. pkID uint64
  117. row []types.FieldValue
  118. keys []interface{}
  119. idx int
  120. }
  121. // topkHeap 容量上限 limit+offset 的小顶堆: 超过即弹出当前最小, 堆里始终是
  122. // 已见行中的前 k 名。heap.Interface。
  123. type topkHeap struct {
  124. specs []orderKeySpec
  125. items []topkItem
  126. }
  127. func (h *topkHeap) Len() int { return len(h.items) }
  128. // Less 定义"输出序的逆序" (大顶堆): 堆顶是【当前集合里最后输出】的元素 ——
  129. // 容量超限时的淘汰对象。相等键时输入序号大者更靠后、先被淘汰 (稳定)。
  130. func (h *topkHeap) Less(i, j int) bool {
  131. c := compareKeys(h.items[i].keys, h.items[j].keys, h.specs)
  132. if c != 0 {
  133. return c > 0
  134. }
  135. return h.items[i].idx > h.items[j].idx
  136. }
  137. func (h *topkHeap) Swap(i, j int) { h.items[i], h.items[j] = h.items[j], h.items[i] }
  138. func (h *topkHeap) Push(x interface{}) { h.items = append(h.items, x.(topkItem)) }
  139. func (h *topkHeap) Pop() interface{} {
  140. old := h.items
  141. n := len(old)
  142. it := old[n-1]
  143. old[n-1] = topkItem{} // 防内存泄漏
  144. h.items = old[:n-1]
  145. return it
  146. }
  147. // cmpInt64 / cmpUint64 把三态比较收敛到一处, 避免每个分支重复写一遍 if 链。
  148. func cmpInt64(a, b int64) int {
  149. switch {
  150. case a < b:
  151. return -1
  152. case a > b:
  153. return 1
  154. }
  155. return 0
  156. }
  157. func cmpUint64(a, b uint64) int {
  158. switch {
  159. case a < b:
  160. return -1
  161. case a > b:
  162. return 1
  163. }
  164. return 0
  165. }
  166. // compareFieldValues 按【字段类型】比较同一列的两个值, 返回 -1/0/1。
  167. //
  168. // 类型必须由调用方传入, 不能只看 Go 值类型: 同一列都可能读成 int16, 但它既可能来自
  169. // 有符号的 FieldType_Int16 (int16 语义), 也可能来自无符号的 FieldType_Uint16 ——
  170. // 后者的值是 uint16 的位模式被重解释成 int16, 两者序不同 (位模式 0xFFFF: int16 是 -1,
  171. // uint16 是 65535)。旧实现只按 Go 值类型分派, 既分不清这两种, 又整个漏掉了 int8/int64。
  172. //
  173. // 有符号类型比的是【解码后的值】而不是盘上字节: 盘上是保序编码 (符号位已翻转),
  174. // 直接比字节也对, 但这里拿到的是已解码的值, 比数值更直白。
  175. func compareFieldValues(a, b interface{}, ft types.FieldType) int {
  176. switch ft {
  177. case types.FieldType_Int8:
  178. return cmpInt64(int64(a.(int8)), int64(b.(int8)))
  179. case types.FieldType_Int16:
  180. return cmpInt64(int64(a.(int16)), int64(b.(int16)))
  181. case types.FieldType_Int32:
  182. return cmpInt64(int64(a.(int32)), int64(b.(int32)))
  183. case types.FieldType_Int64:
  184. return cmpInt64(a.(int64), b.(int64))
  185. case types.FieldType_Uint8:
  186. return cmpUint64(uint64(a.(byte)), uint64(b.(byte)))
  187. case types.FieldType_Uint16:
  188. // 无符号: 先把 int16 位模式还原回 uint16 再比, 否则 > 32767 的值会被当成负数
  189. return cmpUint64(uint64(uint16(a.(int16))), uint64(uint16(b.(int16))))
  190. case types.FieldType_Uint32:
  191. return cmpUint64(uint64(uint32(a.(int32))), uint64(uint32(b.(int32))))
  192. case types.FieldType_Uint64:
  193. return cmpUint64(a.(uint64), b.(uint64))
  194. case types.FieldType_DateTime:
  195. return cmpUint64(a.(uint64), b.(uint64))
  196. case types.FieldType_Float64:
  197. // 同一列读出的一定是同一类型, 故 b 也是 float64; 容错地走 toFloat64
  198. fa, fb := toFloat64(a), toFloat64(b)
  199. switch {
  200. case fa < fb:
  201. return -1
  202. case fa > fb:
  203. return 1
  204. }
  205. return 0
  206. case types.FieldType_Float32:
  207. fa, fb := a.(float32), b.(float32)
  208. switch {
  209. case fa < fb:
  210. return -1
  211. case fa > fb:
  212. return 1
  213. }
  214. return 0
  215. case types.FieldType_Bool:
  216. // false < true (与盘上 0x00 < 0x01 的字节序一致)
  217. ba, bb := a.(bool), b.(bool)
  218. switch {
  219. case ba == bb:
  220. return 0
  221. case !ba:
  222. return -1
  223. }
  224. return 1
  225. case types.FieldType_Year:
  226. // 同 uint16: 载体是 int16, 但语义是无符号年份
  227. return cmpUint64(uint64(uint16(a.(int16))), uint64(uint16(b.(int16))))
  228. case types.FieldType_Decimal:
  229. // 走数值比较 (自动对齐 scale): 同一列的 scale 必然相同, 但比较函数不该依赖这一点
  230. return a.(types.Decimal).Cmp(b.(types.Decimal))
  231. case types.FieldType_Int128:
  232. na, oka := a.(*big.Int)
  233. nb, okb := b.(*big.Int)
  234. if !oka || !okb {
  235. return 0
  236. }
  237. return na.Cmp(nb)
  238. case types.FieldType_UUID:
  239. ua, oka := a.(types.UUID)
  240. ub, okb := b.(types.UUID)
  241. if !oka || !okb {
  242. return 0
  243. }
  244. return bytes.Compare(ua[:], ub[:])
  245. }
  246. // 动态字段与所有定长字符串: 按字节序
  247. ba, ok := a.([]byte)
  248. if !ok {
  249. return 0
  250. }
  251. bb, ok := b.([]byte)
  252. if !ok {
  253. return 0
  254. }
  255. return bytes.Compare(ba, bb)
  256. }
  257. // fieldTypeOf 取某列的存储类型, 供按类型比较/聚合使用; 列不存在时返回 0。
  258. func (q *Query) fieldTypeOf(name string) types.FieldType {
  259. if i := q.table.findFieldIndex(name); i >= 0 {
  260. return q.table.Field[i].FieldType
  261. }
  262. return 0
  263. }
  264. // ======================== 流式聚合 ========================
  265. // FindOne 流式查询,返回单行 (命中即停,不遍历全表)
  266. func (q *Query) FindOne() ([]types.FieldValue, error) {
  267. var result []types.FieldValue
  268. found := false
  269. err := q.scan(func(row []types.FieldValue) bool {
  270. result = row
  271. found = true
  272. return false // 找到第一行即停止
  273. })
  274. if err != nil {
  275. return nil, err
  276. }
  277. if !found {
  278. return nil, page.ErrNotFound
  279. }
  280. return result, nil
  281. }
  282. // Count 流式计数。
  283. //
  284. // 三级加速 (每级都严格保持与全量扫描相同的计数语义):
  285. // 1. 无条件无分页排序 → 逐页数活行 (DataPage::CountLiveRows), 不物化、不解码;
  286. // 2. WHERE 被索引区间完全消费 (remainingCond == nil) → 直接数索引条目,
  287. // 不回表、不反序列化 —— 旧实现这里每个命中行都做一次 ResolveByPK +
  288. // deserializeRow, "用索引 COUNT" 反而比全表扫描更慢 (20k 行 632ms);
  289. // 3. 其余 → 裸字节扫描计数 (deserializeField 都不需要)。
  290. // 带 OFFSET/LIMIT/ORDER BY 时保持旧行为 (旧实现的 Count 语义上会先被分页截断)。
  291. func (q *Query) Count() (int64, error) {
  292. paged := q.limit > 0 || q.offset > 0 || len(q.orderBys) > 0
  293. if !paged && q.whereCond == nil {
  294. return q.countAllLive(), nil
  295. }
  296. if !paged {
  297. if plan := q.buildScanPlan(); plan != nil && plan.remainingCond == nil {
  298. var count int64
  299. for _, kr := range plan.ranges {
  300. err := plan.handler.RangeScan(q.table.handle, plan.meta.EntryPage,
  301. kr.startKey, kr.endKey, kr.startInclusive, kr.endInclusive, false,
  302. func(row []byte) bool {
  303. if len(row) >= 8 {
  304. count++
  305. }
  306. return true
  307. })
  308. if err != nil {
  309. return 0, err
  310. }
  311. }
  312. return count, nil
  313. }
  314. var count int64
  315. err := q.scanRaw(func(_ uint64, _ []byte) bool {
  316. count++
  317. return true
  318. })
  319. return count, err
  320. }
  321. var count int64
  322. err := q.scan(func(row []types.FieldValue) bool {
  323. count++
  324. return true
  325. })
  326. return count, err
  327. }
  328. // countAllLive 逐页累加活行数 (无条件 COUNT(*) 的 O(页数) 路径)。
  329. func (q *Query) countAllLive() int64 {
  330. if q.table.indexMeta == nil {
  331. return 0
  332. }
  333. primMeta, primHandler, ok := q.table.indexMeta.rowStoreMeta()
  334. if !ok || primMeta == nil || primHandler == nil {
  335. return 0
  336. }
  337. // 处理器实现了免物化计数就用它; 否则退回"读全部行再取 len"
  338. type liveCounter interface {
  339. ReadDataPageLiveCount(handle page.HandleDb, dpID uint32) int
  340. }
  341. counter, canCount := primHandler.(liveCounter)
  342. var total int64
  343. for _, dpID := range primHandler.GetDataPageIDs(q.table.handle, primMeta.EntryPage) {
  344. if canCount {
  345. total += int64(counter.ReadDataPageLiveCount(q.table.handle, dpID))
  346. continue
  347. }
  348. total += int64(len(primHandler.ReadDataPageRows(q.table.handle, dpID)))
  349. }
  350. return total
  351. }
  352. // Sum 流式求和。
  353. // 每行只解码目标一列 (Table.deserializeField), 不再物化整行; 带 ORDER BY 时
  354. // 排序管线需要整行, 保持旧路径。条件过滤 (whereCond/remainingCond) 在裸字节上
  355. // 进行, 与旧路径同一套 Match。
  356. func (q *Query) Sum(col string) (float64, error) {
  357. if len(q.orderBys) > 0 {
  358. var sum float64
  359. err := q.scan(func(row []types.FieldValue) bool {
  360. for _, fv := range row {
  361. if string(fv.FieldName) == col {
  362. sum += toFloat64(fv.Value)
  363. break
  364. }
  365. }
  366. return true
  367. })
  368. return sum, err
  369. }
  370. var sum float64
  371. err := q.scanRaw(func(_ uint64, rowData []byte) bool {
  372. if v, ok := q.table.deserializeField(rowData, col); ok {
  373. sum += toFloat64(v)
  374. }
  375. return true
  376. })
  377. return sum, err
  378. }
  379. // Max 流式求最大值。
  380. //
  381. // 加速分两档:
  382. // 1. 目标列是某二级索引首列且无 WHERE/分页/排序 → 直接取索引端点
  383. // (反向 RangeScan 第一条即最大键), O(log N) —— 旧实现对 100 万行
  384. // 线性扫 1.4s, MySQL/SQLite 同场景是 2.6ms/45µs;
  385. // 2. 其余 → 裸字节扫描, 每行只解码目标一列。
  386. func (q *Query) Max(col string) (interface{}, error) {
  387. if v, hit, err := q.minMaxViaIndex(col, true); hit || err != nil {
  388. return v, err
  389. }
  390. ft := q.fieldTypeOf(col)
  391. if len(q.orderBys) > 0 {
  392. var maxVal interface{}
  393. err := q.scan(func(row []types.FieldValue) bool {
  394. for _, fv := range row {
  395. if string(fv.FieldName) == col {
  396. if maxVal == nil || compareFieldValues(fv.Value, maxVal, ft) > 0 {
  397. maxVal = fv.Value
  398. }
  399. break
  400. }
  401. }
  402. return true
  403. })
  404. return maxVal, err
  405. }
  406. var maxVal interface{}
  407. err := q.scanRaw(func(_ uint64, rowData []byte) bool {
  408. if v, ok := q.table.deserializeField(rowData, col); ok {
  409. if maxVal == nil || compareFieldValues(v, maxVal, ft) > 0 {
  410. maxVal = v
  411. }
  412. }
  413. return true
  414. })
  415. return maxVal, err
  416. }
  417. // Min 流式求最小值 (加速路径同 Max, 端点取正向第一条)。
  418. func (q *Query) Min(col string) (interface{}, error) {
  419. if v, hit, err := q.minMaxViaIndex(col, false); hit || err != nil {
  420. return v, err
  421. }
  422. ft := q.fieldTypeOf(col)
  423. if len(q.orderBys) > 0 {
  424. var minVal interface{}
  425. err := q.scan(func(row []types.FieldValue) bool {
  426. for _, fv := range row {
  427. if string(fv.FieldName) == col {
  428. if minVal == nil || compareFieldValues(fv.Value, minVal, ft) < 0 {
  429. minVal = fv.Value
  430. }
  431. break
  432. }
  433. }
  434. return true
  435. })
  436. return minVal, err
  437. }
  438. var minVal interface{}
  439. err := q.scanRaw(func(_ uint64, rowData []byte) bool {
  440. if v, ok := q.table.deserializeField(rowData, col); ok {
  441. if minVal == nil || compareFieldValues(v, minVal, ft) < 0 {
  442. minVal = v
  443. }
  444. }
  445. return true
  446. })
  447. return minVal, err
  448. }
  449. // minMaxViaIndex 取索引端点求 Max/Min。
  450. //
  451. // 前提: 目标列是某个二级索引的首列, 且查询不带 WHERE/分页/排序 —— 此时
  452. // "全表最大值"就是"该索引里最大的键" (索引键编码与行内字节同源, 字节序即值序,
  453. // 见 encodeIndexKey 的说明), 反向 (Max) / 正向 (Min) RangeScan 的第一条即答案。
  454. // 回调返回 false 提前终止遍历, 成本只有一次树下降。
  455. //
  456. // 返回 (值, 是否命中快速路径, err); 未命中时调用方走全扫路径。
  457. func (q *Query) minMaxViaIndex(col string, wantMax bool) (interface{}, bool, error) {
  458. if q.whereCond != nil || q.limit > 0 || q.offset > 0 || len(q.orderBys) > 0 {
  459. return nil, false, nil
  460. }
  461. if q.table.indexMeta == nil {
  462. return nil, false, nil
  463. }
  464. for i := range q.table.indexMeta.metas {
  465. m := &q.table.indexMeta.metas[i]
  466. if m.Flag&0x80 != 0 || m.IndexType == page.IndexTypePrimary {
  467. continue
  468. }
  469. if q.fieldNameFromMeta(m) != col {
  470. continue
  471. }
  472. if _, ok := q.buildKeyLayout(m); !ok {
  473. continue // 索引当前不可用 (列被删 / 动态列), 退回全扫
  474. }
  475. handler, ok := index.Compose.GetHandler(m.IndexType)
  476. if !ok {
  477. continue
  478. }
  479. var (
  480. got interface{}
  481. found bool
  482. )
  483. err := handler.RangeScan(q.table.handle, m.EntryPage,
  484. nil, nil, true, true, wantMax,
  485. func(row []byte) bool {
  486. if len(row) < 8 {
  487. return true
  488. }
  489. storeRow, ok := q.table.indexMeta.ResolveByPK(binary.BigEndian.Uint64(row[:8]))
  490. if !ok {
  491. return true // 端点条目解不出行: 索引端点不可信, 由外层退回全扫
  492. }
  493. if v, ok := q.table.deserializeField(storeRow[8:], col); ok {
  494. got, found = v, true
  495. }
  496. return false // 只取端点一条
  497. })
  498. if err != nil || !found {
  499. return nil, false, err
  500. }
  501. return got, true, nil
  502. }
  503. return nil, false, nil
  504. }
  505. func toFloat64(v interface{}) float64 {
  506. switch val := v.(type) {
  507. case float64:
  508. return val
  509. case float32:
  510. return float64(val)
  511. case uint64:
  512. return float64(val)
  513. case int64:
  514. return float64(val)
  515. case int:
  516. return float64(val)
  517. case int8:
  518. return float64(val)
  519. case int16:
  520. return float64(val)
  521. case int32:
  522. return float64(val)
  523. case byte:
  524. return float64(val)
  525. case bool:
  526. if val {
  527. return 1
  528. }
  529. return 0
  530. case types.Decimal:
  531. // 近似: decimal → float64 会失真, 但 Sum/Avg 的返回值类型就是 float64。
  532. // 需要精确求和的金额场景请用 Decimal.Add 自行累加。
  533. return val.Float64()
  534. case *big.Int:
  535. if val == nil {
  536. return 0
  537. }
  538. f, _ := new(big.Float).SetInt(val).Float64()
  539. return f
  540. }
  541. return 0
  542. }