数据库的范围查询
范围查询
B+树迭代器
迭代器接口
B+树的基本操作包括用于范围查询的查找和迭代。B+树的位置由状态化的迭代器 BIter
表示。
// 查找小于或等于输入键的最近位置
func (tree *BTree) SeekLE(key []byte) *BIter// 获取当前键值对
func (iter *BIter) Deref() ([]byte, []byte)// Deref() 的前置条件检查
func (iter *BIter) Valid() bool// 向前或向后移动
func (iter *BIter) Prev()
func (iter *BIter) Next()
例如,对于查询 a <= key
的操作可以这样实现:
for iter := tree.SeekLE(key); iter.Valid(); iter.Prev() {k, v := iter.Deref()// ...
}
导航树结构
为了在节点内找到当前键的兄弟键,需要知道当前键的位置。如果兄弟键位于兄弟节点中,则需要回溯到父节点。由于不使用父指针,因此需要从根到叶的完整路径。
type BIter struct {tree *BTreepath []BNode // 根到叶的路径pos []uint16 // 节点中的索引
}
移动迭代器类似于逐位递增数字时的进位操作。
func (iter *BIter) Next() {iterNext(iter, len(iter.path)-1)
}func iterNext(iter *BIter, level int) {if iter.pos[level]+1 < iter.path[level].nkeys() {iter.pos[level]++ // 在当前节点内移动} else if level > 0 {iterNext(iter, level-1) // 移动到兄弟节点} else {iter.pos[len(iter.pos)-1]++ // 超出最后一个键return}if level+1 < len(iter.pos) { // 更新子节点node := iter.path[level]kid := BNode(iter.tree.get(node.getPtr(iter.pos[level])))iter.path[level+1] = kiditer.pos[level+1] = 0}
}
查找键
查找键类似于点查询,但会记录路径。
func (tree *BTree) SeekLE(key []byte) *BIter {iter := &BIter{tree: tree}for ptr := tree.root; ptr != 0; {node := tree.get(ptr)idx := nodeLookupLE(node, key)iter.path = append(iter.path, node)iter.pos = append(iter.pos, idx)ptr = node.getPtr(idx)}return iter
}
nodeLookupLE
是用于小于等于比较的函数,你还需要其他比较操作符。
const (CMP_GE = +3 // >=CMP_GT = +2 // >CMP_LT = -2 // <CMP_LE = -3 // <=
)func (tree *BTree) Seek(key []byte, cmp int) *BIter
9.2 保持顺序的编码
对任意数据进行字节字符串排序
我们的B+树处理的是任意字节的字符串键,但列可以是其他类型的数据,如数字,而且键可以是多个列。为了支持范围查询,序列化后的键必须根据其数据类型进行比较。
一种明显的方法是用一个回调函数替换 bytes.Compare
,该回调函数根据表模式解码并比较键。另一种方法是选择一个特殊的序列化格式,使得生成的字节能够反映排序顺序。这是我们将采用的快捷方式。
数字
首先解决一个简单的问题:如何编码无符号整数,以便可以通过 bytes.Compare
比较它们?bytes.Compare
逐字节工作直到遇到差异。因此,在比较中第一个字节是最显著的。如果我们首先放置整数的最高有效(高位)位,那么它们就可以逐字节比较了。这正是大端整数。
接下来考虑有符号整数,它通过补码表示。在补码表示中,无符号值的上半部分只是偏移到负值。为了确保正确的顺序,正半部分与负半部分交换,这仅仅是翻转最高有效位。
var buf [8]byte
u := uint64(v.I64) + (1 << 63)
// 翻转符号位
binary.BigEndian.PutUint64(buf[:], u) // 大端
一些例子:
int64 | Encoded bytes
--------|-----------------
MinInt64| 00 00 00 00 00 00 00 00
-2 | 7f ff ff ff ff ff ff fe
-1 | 7f ff ff ff ff ff ff ff
0 | 80 00 00 00 00 00 00 00
1 | 80 00 00 00 00 00 00 01
MaxInt64| ff ff ff ff ff ff ff ff
一般思路:
- 排列比特,使更高有效位先出现(大端)。
- 将比特重新映射为按正确顺序排列的无符号整数。
练习:将此应用于浮点数(符号+量级+指数)。
字符串
键可以是多列,但是 bytes.Compare
只适用于单个字符串列,因为它需要长度。我们不能简单地连接字符串列,因为这会造成歧义。例如,(“a”, “bc”) vs (“ab”, “c”)。
有两种编码带有长度的字符串的方式,一种是在前面添加长度,这需要解码;另一种是在末尾放一个分隔符,比如空字节。前面的例子编码为 "a\x00bc\x00"
和 "ab\x00c\x00"
。
分隔符的问题在于输入中不能包含分隔符,这通过转义分隔符来解决。我们将使用字节 0x01
作为转义字节,并且转义字节本身也必须被转义。所以我们需要两种转换:
00 -> 01 01
01 -> 01 02
注意,转义序列仍然保留排序顺序。
元组
多列比较(元组)是逐列进行的,直到遇到差异为止。这就像字符串比较一样,除了每个项是一个类型值而不是字节。只要没有歧义,我们可以简单地串联每个列的编码字节。
9.3 范围查询
扫描器(Scanner)
扫描器是B+树迭代器的一个封装,它将键值对解码为行数据。
Valid()
:判断当前是否在范围内。Next()
:移动底层的B树迭代器。Deref(rec *Record)
:获取当前行。db.Scan(table string, req *Scanner) error
:执行范围查询并返回结果。
// 是否在范围内?
func (sc *Scanner) Valid() bool// 移动底层的B树迭代器
func (sc *Scanner) Next()// 获取当前行
func (sc *Scanner) Deref(rec *Record)func (db *DB) Scan(table string, req *Scanner) error
输入是一个主键的区间。Scanner
结构体定义如下:
type Scanner struct {// 范围,从Key1到Key2Cmp1 int // CMP_?? 比较操作符Cmp2 intKey1 Record // 起始键Key2 Record // 结束键// ...
}
对于开区间的情况,只需将 Key2
设置为最大或最小值即可。
9.4 我们学到了什么
- B+树迭代器:我们了解了如何使用状态化的迭代器遍历B+树,包括查找特定键、向前向后移动等操作。
- 保持顺序的编码:学习了如何对不同类型的数据进行编码,以确保它们在字节级别上保持正确的顺序。这对于支持范围查询至关重要。
下一步将是添加二级索引,这实际上就是额外的表结构,用于加速某些类型的查询。例如,一个二级索引可以用来快速查找符合特定条件的所有记录,而不需要遍历整个主表。这涉及到创建新的表来存储索引信息,并实现相应的查询逻辑以便于利用这些索引来提高查询效率。
代码仓库地址:database-go
相关文章:
数据库的范围查询
范围查询 B树迭代器 迭代器接口 B树的基本操作包括用于范围查询的查找和迭代。B树的位置由状态化的迭代器 BIter 表示。 // 查找小于或等于输入键的最近位置 func (tree *BTree) SeekLE(key []byte) *BIter// 获取当前键值对 func (iter *BIter) Deref() ([]byte, []byte)/…...
JS DAY4 日期对象与节点
一日期对象 日期对象:用来表示时间的对象 作用:可以得到当前系统时间 1.实例化 在代码中发现了 new 关键字时,一般将这个操作称为实例化 创建一个时间对象并获取时间 时间必须实例化 获得当前时间 const date new Date() 获得指定时间 const date new Date(…...
【Leetcode 每日一题 - 补卡】1007. 行相等的最少多米诺旋转
问题背景 在一排多米诺骨牌中, t o p s [ i ] tops[i] tops[i] 和 b o t t o m s [ i ] bottoms[i] bottoms[i] 分别代表第 i i i 个多米诺骨牌的上半部分和下半部分。(一个多米诺是两个从 1 1 1 到 6 6 6 的数字同列平铺形成的 —— 该平铺的每一半…...
Android设备运行yolov8
放假这几天搞了一个基于uniapprk3588实现了一版yolo检测 这个是基于前端调用后端api来实现,感觉还可以,但是需要有网络才能进行图像检测,网络不稳定就会出现等待时间会比较久的问题,然后有做了一个在做了一个Android版本的图像检…...
Debezium MySqlValueConverters详解
Debezium MySqlValueConverters详解 1. 类的作用与功能 1.1 核心作用 MySqlValueConverters是Debezium中负责MySQL数据类型转换的核心类,主要功能包括: 数据类型映射:将MySQL的数据类型映射到Kafka Connect的Schema类型值转换:将MySQL的原始值转换为Kafka Connect可用的…...
Redis从入门到实战——实战篇(下)
四、达人探店 1. 发布探店笔记 探店笔记类似于点评网站的评价,往往是图文结合。对应的表有两个: tb_blog:探店笔记表,包含笔记中的标题、文字、图片等tb_blog_comments:其他用户对探店笔记的评价 步骤①࿱…...
算法中的数学:质数(素数)
1.质数 1.1定义 一个大于1的自然数,除了1和它自身外,不能被其他自然数整除,那么他就是质数,否则他就是合数。 注意:1既不是质数也不是合数 唯一的偶质数是2,其余所有质数都是奇质数 1.2质数判定求法 试除法…...
linux、window安装部署nacos
本文以nacos 2.2.0为例 文章目录 1.下载安装包2.按需修改配置配置单机模式配置内存 -Xms -Xmx -Xmn配置数据库为MySQL 3. 访问http://ip:8848/nacos4.常见问题找不到javac命令 1.下载安装包 打开官网,下载2.2.0版本 2.按需修改配置 配置单机模式 默认集群模式&…...
C++ 外观模式详解
外观模式(Facade Pattern)是一种结构型设计模式,它为复杂的子系统提供一个简化的接口。 概念解析 外观模式的核心思想是: 简化接口:为复杂的子系统提供一个更简单、更统一的接口 降低耦合:减少客户端与子…...
42. 接雨水(相向双指针/前后缀分解),一篇文章讲透彻
给定一个数组,代表柱子的高度 求出下雨之后,能接的水有多少单位。我们将每一个柱子想象成一个水桶,看他能接多少水 以这个水桶为例,他所能接的水取决于左边的柱子的最大高度和右边柱子的最大高度,因为只有柱子高的时候…...
vue实现AI问答Markdown打字机效果
上线效果 功能清单 AI问答,文字输出跟随打字机效果格式化回答内容(markdown格式)停止回答,复制回答内容回答时自动向下滚动全屏切换历史问答查看 主要技术 vue 2.7.1markdown-it 14.1.0microsoft/fetch-event-source 2.0.1high…...
【QT】QT中的事件
QT中的事件 1.事件的定义和作用2.QT中事件产生和派发流程2.1 步骤2.2 图示示例代码:(event函数接收所有事件) 3.常见的事件3.1 鼠标事件示例代码:现象: 3.2 按键事件3.3 窗口大小改变事件 4.举例说明示例代码ÿ…...
【QT】QT中的软键盘设计
QT的软键盘设计 1.软键盘制作步骤2.介绍有关函数的使用3.出现的编译错误及解决办法示例代码1:按键事件实现软键盘现象:示例代码2:按键事件实现软键盘(加特殊按键)现象: 软键盘移植到新的工程的步骤…...
【Unity】一个AssetBundle热更新的使用小例子
1.新建两个预制体: Cube1:GameObject Material1:Material Cube1使用了Material1材质 之后设置打包配置 Cube1的打包配置为custom.ab Material1的打包配置为mat.ab 2.在Asset文件夹下创建Editor文件夹,并在Editor下创建BuildBundle…...
【Bootstrap V4系列】学习入门教程之 组件-按钮组(Button group)
Bootstrap V4系列 学习入门教程之 组件-按钮组(Button group) 按钮组(Button group)一、Basic example二、Button toolbar 按钮工具条三、Sizing 尺寸四、Nesting 嵌套五、Vertical variation 垂直变化 按钮组(Button …...
Linux进程间的通信
IPC 即 Inter-Process Communication,也就是进程间通信,它指的是在不同进程之间进行数据交换和协调同步的机制。在操作系统里,每个进程都有自己独立的内存空间,一般情况下不能直接访问其他进程的内存,所以需要借助 IPC…...
常用非对称加密算法的Python实现及详解
非对称加密算法(Asymmetric Encryption)使用公钥加密、私钥解密,解决了对称加密的密钥分发问题。本文将详细介绍 RSA、ECC、ElGamal、DSA、ECDSA、Ed25519 等非对称加密算法的原理,并提供Python实现代码及安全性分析。 1. 非对称加…...
【题解-洛谷】B4303 [蓝桥杯青少年组省赛 2024] 字母移位
题目:B4303 [蓝桥杯青少年组省赛 2024] 字母移位 题目描述 字母移位表示将字母按照字母表的顺序进行移动。 例如, b \texttt{b} b 向右移动一位是 c \texttt{c} c, f \texttt{f} f 向左移动两位是 d \texttt{d} d。 特别地,…...
详讲viewer查看器
将Python与Cesium结合起来,可以实现高效的数据处理与可视化展示。本文将详细介绍如何在Python环境中集成Cesium,以及实现数据可视化的具体方法。 我们可以通过在app.vue中的修改来更改我们查看器的显示方法 修改前 修改后 还可以进行各式各样的自定义操作…...
开关电源原理
开关电源原理 一、 开关电源的电路组成: 开关电源的主要电路是由输入电磁干扰滤波器(EMI)、整流滤波电路、功率变换电路、PWM控制器电路、输出整流滤波电路组成。辅助电路有输入过欠压保护电路、输出过欠压保护电路、输出过流保护电路、输出短…...
数据库的并发控制
并发控制 12.1 并发级别 问题:交错的读写 并发客户端可以随意进入和退出事务,并在中途请求读取和写入。为了简化分析,假设enter/exit/read/write是原子步骤,因此并发事务只是这些步骤的交错。 我们还将区分只读事务和读写事务…...
力扣第448场周赛
赛时成绩如下: 这应该是我力扣周赛的最好成绩了(虽然还是三题) 1. 两个数字的最大乘积 给定一个正整数 n。 返回 任意两位数字 相乘所得的 最大 乘积。 注意:如果某个数字在 n 中出现多次,你可以多次使用该数字。 示例 1: 输入࿱…...
关于Python:9. 深入理解Python运行机制
一、Python内存管理(引用计数、垃圾回收) Python(CPython)采用的是: “引用计数为主,垃圾回收为辅” 的内存管理机制。 也就是说: 引用计数机制:负责大部分内存释放,简…...
Cron表达式的用法
最近几天开发东西用到了定时脚本的问题,中间隔了一段时间没有用到,再次复习一下Cron表达式的用法。 Cron表达式是一种用于定义定时任务执行时间的字符串格式,广泛应用于Unix/Linux系统以及各种编程语言中。其主要用途是通过灵活的时间规则来…...
手机通过局域网访问网狐接口及管理后台网站
1.本地部署接口及后台网站 2.设置允许网站端口通过防火墙 3.查看网站服务器IP 4.手机连接到本地服务器同一局域网 5.手机访问本地服务器接口...
JavaSE核心知识点01基础语法01-01(关键字、标识符、变量)
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 JavaSE核心知识点01基础语法01-01࿰…...
Sliding Window Attention(Longformer)
最简单的自注意力大家肯定都会啦。 但这种全连接的自注意力(即每个 token 需要 attend 到输入序列中的所有其他 token)计算与内存开销是 O ( n 2 ) O(n^2) O(n2) 。为了缓解这个问题,研究者们提出了 Sliding Window Attention。 Sliding W…...
ROS2 开发踩坑记录(持续更新...)
1. 从find_package(xxx REQUIRED)说起,如何引用其他package(包) 查看包的安装位置和include路径详细文件列表 例如,xxx包名为pluginlib # 查看 pluginlib 的安装位置 dpkg -L ros-${ROS_DISTRO}-pluginlib | grep include 这条指令的目的是…...
刷leetcodehot100返航版--哈希表5/5、5/6
回顾一下之前做的哈希,貌似只有用到 unordered_set:存储无序元素unordered_map:存储无序键值对 代码随想录 常用代码模板2——数据结构 - AcWing C知识回顾-CSDN博客 1.两数之和5/5【30min】 1. 两数之和 - 力扣(LeetCode&am…...
嵌入式开发学习日志Day13
第九章 预处理命令 前面加“#”的都为预处理命令; 预处理命令是无脑的文本替换; 一、宏定义 1、不带参数的宏定义 一般形式为: #define 标识符 字符串 (谷歌规定):所有的宏名均大写,便于…...
AI预测的艺术品走势靠谱吗?
首席数据官高鹏律师团队 AI预测艺术品价格走势:技术与法律的双重考量在当今数字化浪潮席卷全球的时代,人工智能(AI)技术正以前所未有的速度渗透到各个领域,艺术品市场也不例外。AI预测艺术品价格走势这一新兴事物&…...
AVL树 和 红黑树 的插入算法
1.AVL树 按照二叉搜索树的规则找到要插入的位置并插入,插入过后看是父节点的左还是右孩子,然后把父节点的平衡因子-1或1,调整后如果父节点的平衡因子是0,那就说明这颗子树的高度插入前后不变,上面的就不用调整平衡因子…...
【项目】基于ArkTS的网吧会员应用开发(1)
一、效果图展示 二、界面讲解 以上是基于ArkTS的鸿蒙应用网吧会员软件的引导页,使用滑动组件滑动页面,至最后一页时,点击立即体验,进入登录页面。 三、代码演示 import promptAction from ohos.promptAction; import router fr…...
命令模式(Command Pattern)
非常好!现在我们来深入讲解行为型设计模式之一 —— 命令模式(Command Pattern)。 我将通过: ✅ 定义解释 🎯 使用动机 🐍 Python 完整调用代码(含注释) 🧭 清晰类图 …...
CMake基础介绍
1、CMake 概述 CMake 是一个项目构建工具,并且是跨平台的;关于项目构建目前比较流行的还有 Makefile(通过 Make 命令进行项目的构建), 大多 IDE 软件都集成了 make,比如:VS 的 nmake、linux 下的 GNU make、Qt 的 qmake 等&…...
偷钱包行为检测数据集VOC+YOLO格式922张1类别有增强
有320张图片是原图剩余为增强图片 数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):922 标注数量(xml文件个数):922 标注数量…...
C 语言比较运算符:程序如何做出“判断”?
各类资料学习下载合集 https://pan.quark.cn/s/8c91ccb5a474 在编写程序时,我们经常需要根据不同的条件来执行不同的代码。比如,如果一个分数大于 60 分,就判断为及格;如果用户的年龄小于 18 岁,就禁止访问某个内容等等。这些“判断”的核心,就依赖于程序能够比…...
Webug4.0靶场通关笔记16- 第20关文件上传(截断上传)
目录 第20关 文件上传(截断上传) 1.打开靶场 2.源码分析 (1)右键查看前端源码 (2)服务端源码分析 (3)渗透思路 3.渗透实战 (1)构建脚本 (2)bp抓包 …...
10 种最新的思维链(Chain-of-Thought, CoT)增强方法
防御式链式思维(Chain-of-Defensive-Thought) 该方法通过引入结构化、防御性的推理示例,提高大语言模型在面对被污染或误导信息时的稳健性。 📄 论文链接:https://arxiv.org/abs/2504.20769 混合链式思维(…...
力扣119题解
记录 2025.5.5 题目: 思路: 代码: class Solution {public List<Integer> getRow(int rowIndex) {List<Integer> row new ArrayList<Integer>();row.add(1);for (int i 1; i < rowIndex; i) {row.add((int) ((long) row.get(i…...
NSOperation深入解析:从使用到底层原理
1. 基础概念与使用 1.1 NSOperation概述 NSOperation是Apple提供的一个面向对象的并发编程API,它基于GCD(Grand Central Dispatch)构建,但提供了更高层次的抽象和更丰富的功能。NSOperation允许开发者以面向对象的方式管理并发任…...
suna工具调用可视化界面实现原理分析(二)
这是一个基于React的浏览器操作可视化调试组件,主要用于在AI开发工具中展示网页自动化操作过程(如导航、点击、表单填写等)的执行状态和结果。以下是关键技术组件和功能亮点的解析: 一、核心功能模块 浏览器操作状态可视化 • 实时…...
【大模型面试每日一题】Day 9:BERT 的 MLM 和 GPT 的 Next Token Prediction 有什么区别?
【大模型面试每日一题】Day 9:BERT 的 MLM 和 GPT 的 Next Token Prediction 有什么区别? 📌 题目重现 🌟 面试官:预训练任务中,BERT 的 MLM(Masked Language Modeling)和 GPT 的 …...
分析strtol(),strtoul()和strtod()三个函数的功能
字符串转换为数值部分和子字符串首地址的函数有strtol(),strtoul()和strtod()三个函数。 1、strtol()函数 long int strtol(const char *str, char **endptr, int base) //当base0时,若字符串不是以"0","0x"和"0X"开头,则将数字部分按照10进制…...
Spring Boot 加载application.properties或application.yml配置文件的位置顺序。
我换一种更通俗易懂的方式,结合具体例子来解释 Spring Boot 加载application.properties或application.yml配置文件的位置顺序。 生活场景类比 想象你要找一本书,你有几个可能存放这本书的地方,你会按照一定顺序去这些地方找,直…...
C++进阶之——多态
1. 多态的概念 多态是用来描述这个世界的 多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会 产生出不同的状态。 这里就很厉害了,能够实现特殊处理,本文章就是来仔细…...
第13项三期,入组1123例:默沙东启动TROP2 ADC+PD-1子宫内膜癌头对头临床
Umabs DB作为目前全球最全面的抗体药物专业数据库,收录全球近10000个从临床前到商业化阶段抗体药物,涉及靶点1600,涉及疾病种类2400,研发机构2900,覆盖药物蛋白序列、专利和临床等多种专业信息。Umabs DB药物数据库已正…...
政务服务智能化改造方案和案例分析
政务服务智能化改造方案和案例分析 一、引言 在数字化时代浪潮的推动下,政务服务智能化改造已成为提升政府服务效能、优化营商环境、增强民众满意度的关键举措。传统政务服务模式存在流程繁琐、信息孤岛、办理效率低等问题,难以满足现代社会快节奏发展和…...
15.日志分析入门
日志分析入门 第一部分:日志分析基础第二部分:日志分析方法与工具第三部分:日志分析实践总结 目标: • 理解日志分析在网络安全中的作用 • 掌握日志的基本类型和分析方法 • 通过实践初步体验日志分析的过程 第一部分ÿ…...
EPSG:3857 和 EPSG:4326 的区别
EPSG:3857 和 EPSG:4326 是两种常用的空间参考系统,主要区别在于坐标表示方式和应用场景。以下是它们的核心差异: 1. 坐标系类型 EPSG:4326(WGS84) 地理坐标系(Geographic Coordinate System),基…...