btree_handler.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package index
  2. import (
  3. "TsDB2/DB/core/index/btree"
  4. "TsDB2/DB/core/page"
  5. "bytes"
  6. "encoding/binary"
  7. )
  8. // BTreeHandler — B+ 树二级索引 (IndexTypeBTree)
  9. // 叶子条目: [key(keyLen) + PKID(8B BE)]
  10. type BTreeHandler struct{}
  11. func init() {
  12. Compose.RegisterHandler(page.IndexTypeBTree, &BTreeHandler{})
  13. // 向后兼容:旧数据库中 IndexTypeStr=3 的索引统一用 BTreeHandler 处理
  14. Compose.RegisterHandler(page.IndexTypeStr, &BTreeHandler{})
  15. // 二级 B+ 树分裂参数 —— 写死在本文件, 不随索引元数据传递。
  16. // 二级键分布随机且允许重复, 对半分(50)时平均填充率最高, 故保持 50/50。
  17. btree.SBTSplitCfg = btree.SplitConfig{SplitPercent: 50, SequentialRight: false}
  18. }
  19. func (h *BTreeHandler) Insert(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, rowData []byte, keyLen int) (uint32, error) {
  20. entry := make([]byte, keyLen+8)
  21. copy(entry[:keyLen], indexKey)
  22. binary.BigEndian.PutUint64(entry[keyLen:], pkID)
  23. rootPID := *entryPage
  24. newRoot, err := btree.SBTInsert(rootPID, entry, handle)
  25. if err != nil {
  26. return 0, err
  27. }
  28. *entryPage = newRoot
  29. return newRoot, nil
  30. }
  31. func (h *BTreeHandler) Search(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int, resolve RowResolver) ([]byte, bool) {
  32. rootPID := entryPage
  33. if rootPID == 0 {
  34. return nil, false
  35. }
  36. pkID, found := btree.SBTSearch(rootPID, indexKey[:keyLen], handle)
  37. if !found {
  38. return nil, false
  39. }
  40. // 二级索引不存行数据: 回表由索引自己完成 (上层无需知道主键索引是谁)
  41. if resolve != nil {
  42. if row, ok := resolve(pkID); ok {
  43. return row, true
  44. }
  45. return nil, false
  46. }
  47. pkBuf := make([]byte, 8)
  48. binary.BigEndian.PutUint64(pkBuf, pkID)
  49. return pkBuf, true
  50. }
  51. func (h *BTreeHandler) Delete(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, keyLen int) error {
  52. rootPID := *entryPage
  53. if rootPID == 0 {
  54. return page.ErrNotFound
  55. }
  56. // 二级索引允许重复 key, 用 (key, pkID) 精确定位本行的条目。
  57. // pkID 未知(为 0)时退回按 key 搜索一个条目。
  58. if pkID == 0 {
  59. pk, found := btree.SBTSearch(rootPID, indexKey[:keyLen], handle)
  60. if !found {
  61. return page.ErrNotFound
  62. }
  63. pkID = pk
  64. }
  65. newRoot, err := btree.SBTDeleteWithPKID(rootPID, indexKey[:keyLen], pkID, handle)
  66. if err != nil {
  67. return err
  68. }
  69. *entryPage = newRoot
  70. return nil
  71. }
  72. func (h *BTreeHandler) Update(handle page.HandleDb, entryPage *uint32, oldKey, newKey, rowData []byte, pkID uint64, keyLen int) error {
  73. // 二级索引条目只存 [key + pkID], 不含行数据:
  74. // 键未变 → 无事可做 (过去"先删再插"会让条目在重复 key 区段里错位, 属于多余动作)
  75. // 键变了 → 按 (oldKey, pkID) 精确删旧条目, 再插新条目
  76. if bytes.Equal(oldKey, newKey) {
  77. return nil
  78. }
  79. if oldKey != nil {
  80. if err := h.Delete(handle, entryPage, oldKey, pkID, len(oldKey)); err != nil && err != page.ErrNotFound {
  81. return err
  82. }
  83. }
  84. _, err := h.Insert(handle, entryPage, newKey, pkID, rowData, len(newKey))
  85. return err
  86. }
  87. // IsRowStore 二级索引不承载行数据
  88. func (h *BTreeHandler) IsRowStore() bool { return false }
  89. // ResolveRow 二级索引无法按 pkID 取行, 由调用方的回表函数负责
  90. func (h *BTreeHandler) ResolveRow(handle page.HandleDb, entryPage uint32, pkID uint64, cache *[]DPRange) ([]byte, bool) {
  91. return nil, false
  92. }
  93. // SearchAll 查找相同 key 下的所有 pkID
  94. func (h *BTreeHandler) SearchAll(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]uint64, bool) {
  95. rootPID := entryPage
  96. if rootPID == 0 {
  97. return nil, false
  98. }
  99. return btree.SBTSearchAll(rootPID, indexKey[:keyLen], handle)
  100. }
  101. func (h *BTreeHandler) GetDataPageIDs(handle page.HandleDb, entryPage uint32) []uint32 {
  102. // 二级索引没有 DataPage, 返回空
  103. return nil
  104. }
  105. func (h *BTreeHandler) ReadDataPageRows(handle page.HandleDb, dpID uint32) [][]byte {
  106. // 二级索引没有 DataPage
  107. return nil
  108. }
  109. func (h *BTreeHandler) RangeScan(handle page.HandleDb, entryPage uint32,
  110. startKey, endKey []byte, startInclusive, endInclusive bool, reverse bool,
  111. callback func(row []byte) bool) error {
  112. return btree.SBTRangeScan(entryPage, handle, startKey, endKey, startInclusive, endInclusive, reverse, callback)
  113. }