当前位置: 首页 > news >正文

中国建设银行个人网站银行欧美在线做视频网站

中国建设银行个人网站银行,欧美在线做视频网站,浙江省建设诚信系统网站,宿迁宿豫网站建设二级索引 10.1 二级索引作为额外的键 表结构 正如第8章提到的,二级索引本质上是包含主键的额外键值对。每个索引通过B树中的键前缀来区分。 type TableDef struct {// 用户定义的部分Name stringTypes []uint32 // 列类型Cols []string // 列名Indexes …

在这里插入图片描述

二级索引

10.1 二级索引作为额外的键

表结构

正如第8章提到的,二级索引本质上是包含主键的额外键值对。每个索引通过B+树中的键前缀来区分。

type TableDef struct {// 用户定义的部分Name    stringTypes   []uint32 // 列类型Cols    []string // 列名Indexes [][]string // 第一个索引是主键// 自动分配的B+树键前缀,用于不同的表和索引Prefixes []uint32
}

第一个索引被用作主键,因为它本身也是一个索引。

键值结构

对于二级索引,我们可以将主键存储在B+树的值中,以便通过它找到完整的行数据。然而,与主键不同的是,二级索引通常没有唯一性约束,因此可能会出现重复的B+树键。

为了避免修改B+树以支持重复键,我们可以将主键附加到B+树的键上,使其唯一,并将值留空。

例如:

create table t1 (k1 string,k2 int,v1 string,v2 string,primary key (k1, k2),index idx1 (v1),index idx2 (v2, k2)
);

对应的KV结构如下:

  • 主表 t1:
    • 键:prefix1, k1, k2
    • 值:v1, v2
  • 索引 idx1:
    • 键:prefix2, v1, k1, k2
    • 值:(empty)
  • 索引 idx2:
    • 键:prefix3, v2, k2, k1
    • 值:(empty)

10.2 使用二级索引

通过匹配列选择索引

为了执行范围查询,我们必须选择一个与查询键匹配的索引。这个信息存储在 Scanner 类型中,以便 Scanner.Deref() 可以使用它。

type Scanner struct {// 范围,从 Key1 到 Key2Cmp1 int // CMP_??Cmp2 intKey1 RecordKey2 Record// 内部字段db     *DBtdef   *TableDefindex  int // 使用哪个索引?iter   *BIter // 底层的B+树迭代器keyEnd []byte // 编码后的 Key2
}

索引可以由多列组成。例如,索引 (a, b) 可以服务于查询 (a, b) > (1, 2)。它也可以服务于查询 a > 1,因为这等价于 (a, b) > (1, +∞)。索引的选择仅仅是通过匹配列完成的。

func dbScan(db *DB, tdef *TableDef, req *Scanner) error {// ...isCovered := func(index []string) bool {key := req.Key1.Colsreturn len(index) >= len(key) && slices.Equal(index[:len(key)], key)}req.index = slices.IndexFunc(tdef.Indexes, isCovered)// ...
}
将缺失列编码为无穷大

在最后一个例子中,查询 a > 1 使用索引 (a, b),但只使用了其中的一列,因此我们需要将剩余的列编码为无穷大。

输入查询使用索引
a > 1(a, b) > (1, +∞)
a ≤ 1(a, b) < (1, +∞)
a ≥ 1(a, b) > (1, -∞)
a < 1(a, b) < (1, -∞)

这可以通过修改我们的保持顺序编码实现。我们选择 \xff 表示正无穷大(+∞),而空字符串表示负无穷大(-∞)。由于没有列会被编码为空字符串,因此在 -∞ 的情况下可以直接忽略缺失的列。而在 +∞ 的情况下,我们需要在每个编码列前添加一个标签,以确保它们不会以 \xff 开头。

// 保持顺序的编码
func encodeValues(out []byte, vals []Value) []byte {for _, v := range vals {out = append(out, byte(v.Type)) // 添加标签:不以 0xff 开头switch v.Type {case TYPE_INT64:var buf [8]byteu := uint64(v.I64) + (1 << 63)binary.BigEndian.PutUint64(buf[:], u) // 大端out = append(out, buf[:]...)case TYPE_BYTES:out = append(out, escapeString(v.Str)...)out = append(out, 0) // 空字符终止default:panic("what?")}}return out
}

我们在每个编码列前添加列类型代码作为标签。这不仅方便调试,还可以通过查看十六进制转储直接解码内容。

这是一个小步骤,用于支持前缀列上的范围查询。

// 用于主键和索引
func encodeKey(out []byte, prefix uint32, vals []Value) []byte {// 4字节的表前缀var buf [4]bytebinary.BigEndian.PutUint32(buf[:], prefix)out = append(out, buf[:]...)// 保持顺序编码的键out = encodeValues(out, vals)return out
}// 用于输入范围,可能是索引键的前缀
func encodeKeyPartial(out []byte, prefix uint32, vals []Value, cmp int,
) []byte {out = encodeKey(out, prefix, vals)if cmp == CMP_GT || cmp == CMP_LE { // 编码缺失列为无穷大out = append(out, 0xff) // 不可达的 +∞} // 否则:-∞ 是空字符串return out
}

10.3 维护二级索引

与主数据同步

更新可能涉及多个带有二级索引的B+树键。当一行被更改时,我们必须删除旧的索引键并插入新的索引键。为此,扩展了B+树接口以返回旧值。

type UpdateReq struct {tree *BTree// 输出Added    bool // 添加了新键Updated  bool // 添加了新键或旧键被更改Old      []byte // 更新前的值// 输入Key []byteVal []byteMode int
}

使用新的信息:

func dbUpdate(db *DB, tdef *TableDef, rec Record, mode int) (bool, error) {// ...// 插入行req := UpdateReq{Key: key, Val: val, Mode: mode}if _, err = db.kv.Update(&req); err != nil {return false, err}// 维护二级索引if req.Updated && !req.Added {// 使用 `req.Old` 删除旧的索引键...}if req.Updated {// 添加新的索引键...}return req.Updated, nil
}
多键更新的原子性

原子性不可组合!即使单个KV操作是原子的,当涉及多个键时,我们也会失去原子性。如果数据库崩溃或在更新二级索引时发生错误,应该回滚到之前的状态。

仅使用 get, set, del 实现这一点非常棘手,这就是为什么简单的KV接口有很大的局限性。下一步是引入事务性KV接口,以允许对多个键甚至并发读取进行原子操作。


10.4 表和索引的总结

  • 行和列作为KV对
  • 范围查询
    • B+树迭代器。
    • 保持顺序的编码。
  • 二级索引
    • 索引选择。
    • 需要一个事务性接口。

代码仓库地址:database-go

http://www.dtcms.com/a/469322.html

相关文章:

  • 2018年网站开发语言如何加强英文网站建设
  • Pandas:机器学习数据处理的核心利器
  • ECharts + AWS 服务联动的揭示板(Dashboard)开发示例
  • 运动控制教学——5分钟学会PRM算法!
  • RK平台Uniapp自启动缓存问题解决
  • Java 大视界 -- Java 大数据在智能家居设备联动与场景自动化中的应用
  • 湛江网站建设方案推广怎样做中考成绩查询网站
  • 1.5 labview几个使用小知识点
  • TypeScript 面试题及详细答案 100题 (11-20)-- 基础类型与类型操作
  • LLMs From Scratch(一)---理解大语言模型
  • 清除 iPhone 数据以便出售:永久删除您的数据
  • 关于在ios系统中签名并安装ipa文件的五种方法,PakePlus打包的ipa文件可以看看
  • 网站首页动画代码澄海区建设局网站
  • 设计模式篇之 单例模式 Singleton
  • C++设计模式_结构型模式_组合模式Composite(树形模式)
  • 反转控制与依赖注入详解:以订单处理系统为例
  • 【Unity每日一记】Unity脚本基础指南
  • Isaac Lab 2.3深度解析:全身控制与增强遥操作如何重塑机器人学习
  • 全美东莞网站建设福建省建设行业企业资质查询网站
  • SpringBoot集成springdoc
  • 【Java开发日记】请介绍类加载过程,什么是双亲委派模型?
  • 算法奇妙屋(五)-链表
  • 从iPhone转移到itel手机的联系人转移指南
  • MySQL实战篇04_Docker入门实战:从零搭建MySQL容器环境
  • 上海网站制作机构做网站后面维护要收钱吗
  • wget 命令速查手册 | HTTP / FTP 文件下载全指南
  • ffmpeg avio使用示例
  • 我把Excel变成了像素画板!用Python实现图片到单元格的映射
  • Android相册高频面试场景分析
  • 郑州建筑公司网站建设网页制作标准