H2 Database Select 语句执行流程

H2 Database Select 语句执行流程

使用

// CREATE TABLE IF NOT EXISTS test(id INT primary key, name VARCHAR(255))
// insert into test(id, name) values(1, 'name1'), (2, 'name2'), (3, 'name3'), (4, 'name4');
String sql = "SELECT * FROM test where id > 1 and name='name3'";
ResultSet rs = stmt.executeQuery(sql);

查询 case:

主键查询
覆盖索引查询
索引查询+回表
多表关联查询

功能

模块

总体流程

Select 语句 SQL 解析
Select 语句 SQL 查询优化计算执行计划的成本创建查询优化器优化查询计划计算最佳查询计划测试并更新最优查询计划创建计划计算计划成本先计算 MVPrimaryIndex 查询计划的成本再获取所有候选的索引计算对应的查询计划更新成本最低的查询计划并返回
Select 语句执行

解析&优化

H2 在执行查询操作之前,会根据不同索引计算对应的成本,然后选择成本最小的索引进行后续查询操作。
单表查询时,会获取表的所有索引。按照主键索引、二级索引的顺序依次计算对应的成本。
然后选择成本最小的索引作为查询计划。

org.h2.command.Parser#parse 
解析sql
org.h2.command.query.Query#prepare 
优化sqlorg.h2.command.query.Select#preparePlan 计算执行计划的成本org.h2.command.query.Optimizer#<init> 创建查询优化器org.h2.command.query.Optimizer#optimize 优化查询计划org.h2.command.query.Optimizer#calculateBestPlan 计算最佳查询计划org.h2.command.query.Optimizer#testPlan 测试并更新最优计划org.h2.table.Plan#<init> 创建一个计划org.h2.table.Plan#calculateCost 计算计划成本初始化成本为1,作为后续成本累乘的基础值遍历所有的表过滤器来计算总成本org.h2.table.TableFilter#getBestPlanItem 获取最佳的计划项org.h2.table.Table#getBestPlanItem 获取最佳的计划项org.h2.table.PlanItem#<init> 初始化一个 PlanItem 对象来存储最佳计划org.h2.mvstore.db.MVPrimaryIndex#getCost 计算初始计划项的成本(primary key)org.h2.index.Index#getCostRangeIndex具体计算成本org.h2.mvstore.db.MVTable#getIndexes 获取所有候选索引遍历所有索引计算当前索引的成本(不同索引有不同索引的计算公式)如果当前索引的成本低于当前最佳计划项的成本,更新最佳计划项更新总成本返回最终计算的成本选择最优计划

执行

执行查询时,会根据上面选定的索引创建对应的迭代器,同时会根据不同的事务隔离级别选择创建不同隔离级别的迭代器(比如 CommittedIterator)。
然后根据索引列的条件迭代索引获取数据,获取后的数据会通过 isConditionMet 判断是否满足 SQL 查询条件,最终决定是否要把该行返回给客户端。

org.h2.command.query.Select#queryWithoutCache
执行查询org.h2.table.TableFilter#lock 加读锁org.h2.command.query.Select#queryFlat执行查询org.h2.result.LazyResult#init0 创建一个LazyResultQueryFlat对象org.h2.result.FetchedResult#next 获取下一行org.h2.result.LazyResult#hasNext 判断是否有下一条记录org.h2.command.query.Select.LazyResultQueryFlat#fetchNextRow 获取下一行org.h2.table.TableFilter#next 获取下一行数据org.h2.index.IndexCursor#find 创建 index cursor, 用于迭代数据org.h2.index.IndexCursor#prepareorg.h2.mvstore.db.MVPrimaryIndex#find 从 index 里获取 row, 比如 primary indexorg.h2.mvstore.db.MVPrimaryIndex#getMap 获取 transaction maporg.h2.mvstore.tx.TransactionMap#entryIterator 根据不同隔离级别创建不同迭代器,比如 CommittedIteratororg.h2.index.IndexCursor#next 通过迭代器获取下一行数据org.h2.mvstore.db.MVPrimaryIndex.MVStoreCursor#next 通过主键索引获取下一行数据org.h2.mvstore.tx.TransactionMap.CommittedIterator#fetchNext 获取读已提交数据org.h2.mvstore.Cursor#hasNext 迭代到叶子节点获取下一行数据,返回是否存在下一行数据org.h2.mvstore.Page.Leaf#getValue获取当前值org.h2.mvstore.Cursor#next 获取下一行数据org.h2.command.query.Select#isConditionMet判断当前行是否满足查询条件
迭代索引获取数据

Cursor#hasNext 方法主要用于判断迭代器是否还有下一个元素。
如果有下一个元素,则更新 cursor 里的当前 index 和 当前 index 里对应的 lastValue。
在迭代时,如果到达页面边界时需要向上移动到父页面(从父页面再查找对应的孩子节点),当处于非叶页面时需要向下移动到叶页面,然后从叶子节点上根据 index 获取 value。
相关代码如下:

public boolean hasNext() {if (cursorPos != null) {int increment = reverse ? -1 : 1;while (current == null) { // 循环Page<K,V> page = cursorPos.page; // 当前页面int index = cursorPos.index; // 从 pos 里获取当前 indexif (reverse ? index < 0 : index >= upperBound(page)) { // 判断是否到达当前page的边界// traversal of this page is over, going up a level or stop if at the root alreadyCursorPos<K,V> tmp = cursorPos;cursorPos = cursorPos.parent; // 如果 index 达到当前页的边界,则向上回溯到父节点if (cursorPos == null) {return false;}tmp.parent = keeper;keeper = tmp;} else {// traverse down to the leaf taking the leftmost pathwhile (!page.isLeaf()) { // 如果当前页不是叶子节点,则向下遍历到叶子节点page = page.getChildPage(index);index = reverse ? upperBound(page) - 1 : 0;if (keeper == null) {cursorPos = new CursorPos<>(page, index, cursorPos);} else {CursorPos<K,V> tmp = keeper;keeper = keeper.parent;tmp.parent = cursorPos;tmp.page = page;tmp.index = index;cursorPos = tmp;}}if (reverse ? index >= 0 : index < page.getKeyCount()) {K key = page.getKey(index); // 获取当前 page 指定 index 里存储的 keyif (to != null && Integer.signum(page.map.getKeyType().compare(key, to)) == increment) {return false;}current = last = key;lastValue = page.getValue(index); // 根据 key 获取 valuelastPage = page;}}cursorPos.index += increment; // 增加 index, 移动到下一个位置}}return current != null;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/79217.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

理解 Envoy 的架构

理解 Envoy 的架构对于深入理解 Istio 至关重要&#xff0c;因为 Envoy 是 Istio 数据平面的核心。Envoy 是一个高性能的 C 分布式代理&#xff0c;设计为云原生应用和大规模微服务架构的网络基础。 以下是 Envoy 架构的关键组成部分和核心理念&#xff1a; 核心设计理念&…

Android开发-常用布局

在Android应用开发中&#xff0c;布局决定了用户界面的结构和元素之间的相对位置。选择合适的布局不仅能够提升用户体验&#xff0c;还能提高代码的可维护性和灵活性。本文将介绍几种最常用的Android布局方式&#xff0c;包括LinearLayout、RelativeLayout、ConstraintLayout以…

如何在MySQL中实现类似Redis的PING命令的功能来检测连接状态?

要在MySQL中实现类似Redis的PING命令的功能来检测连接状态&#xff0c;可以采用以下方法&#xff1a; 方法一&#xff1a;使用简单的SQL查询 最直接的方法是通过执行一个简单的查询来检测连接状态&#xff0c;例如&#xff1a; SELECT 1;如果查询成功并返回结果&#xff08;…

Vue 系列之:defineProps、defineEmits、...

defineProps 用于接收父组件传递的属性值。 父组件&#xff1a; <!-- 父组件 --> <template><Child1 str"字符串" :num"num" />-----------------<Child2 str"字符串" :num"num" /> </template><…

windows服务器部署Gitlab

代码托管,如果对工具功能要求不高,Gitea也可以满足需要,只是功能相对比较简单。 通常GltLab是部署在linux服务器上的,windows版本已经不维护了。不过现在windows10 11已经可以实现部署了,一个是windows本机部署linux虚拟机(windows商店直接安装或者其他虚拟机平台都可以)…

剖析 FFmpeg:从基本功能到过滤器,实现音视频处理的灵活性

目录 1.解复用2 解码2.1 音频解码2.2 视频解码 3 修饰3.1 avio3.2 重采样 4 过滤器4.1 过滤器基本知识4.2 简单过滤器4.3 复杂滤镜图 1.解复用 解复用就是把容器中的媒体流分离出来&#xff0c;方便我们对媒体流处理。 step1&#xff1a;对媒体文件上下文初始化 AVFormatCont…

kafka学习笔记(四、生产者、消费者(客户端)深入研究(三)——事务详解及代码实例)

1.事务简介 Kafka事务是Apache Kafka在流处理场景中实现Exactly-Once语义的核心机制。它允许生产者在跨多个分区和主题的操作中&#xff0c;以原子性&#xff08;Atomicity&#xff09;的方式提交或回滚消息&#xff0c;确保数据处理的最终一致性。例如&#xff0c;在流处理中…

Missashe计网复习笔记(随时更新)

Missashe计算机网络复习笔记 前言&#xff1a;这篇笔记用于博主对计网这门课所学进行记录和总结&#xff0c;也包括一些个人的理解。正在更新当中…… 第一章 计算机网络体系结构 考纲内容 (一) 计算机网络概述 计算机网络的概念、组成与功能;计算机网络的分类; 计算机网络…

PVP鼠标推荐(deepseek)

下面有不懂的自行百度查找&#x1f44d; ❤️ 以下是几款在 双击性能&#xff08;DBC&#xff09; 和 拖拽点击&#xff08;DC&#xff09; 方面表现优秀的游戏鼠标推荐&#xff0c;结合了硬件性能、微动寿命以及玩家口碑&#xff1a; 1. 罗技 G102/G203 Lightsync 特点&#…

ABP vNext + EF Core 实战性能调优指南

ABP vNext EF Core 实战性能调优指南 &#x1f680; 目标 本文面向中大型 ABP vNext 项目&#xff0c;围绕查询性能、事务隔离、批量操作、缓存与诊断&#xff0c;系统性地给出优化策略和最佳实践&#xff0c;帮助读者快速定位性能瓶颈并落地改进。 &#x1f4d1; 目录 ABP vN…

为啥大模型一般将kv进行缓存,而q不需要

1. 自回归生成的特点 大模型&#xff08;如 GPT 等&#xff09;在推理时通常采用自回归生成的方式&#xff1a; 模型逐个生成 token&#xff0c;每次生成一个新 token 时&#xff0c;需要重新计算注意力。在生成第 t 个 token 时&#xff0c;模型需要基于前 t-1 个已生成的 t…

3DGS-slam:splatam公式

配套讲解视频&#xff1a;https://www.bilibili.com/video/BV1ZgfBYdEpg/?spm_id_from333.1387.homepage.video_card.click&vd_sourced4c3e747c32049ddd90dcce17208f4e0 1、多维高斯分布公式: 对于多维&#xff08;多变量&#xff09;高斯分布&#xff0c;概率密度函数的…

从Dockerfile 构建docker镜像——保姆级教程

从Dockfile开始 dockerfile简介开始构建1、编辑dockerfile2、构建镜像3、拉取镜像4、推送到镜像仓库 镜像的优化1、优化的基本原则2、多阶段构建 dockerfile简介 开始构建 1、编辑dockerfile # 使用官方的 Python 3.8 镜像作为基础镜像 FROM python:3.8-slim# 设置工作目录 …

开元类双端互动组件部署实战全流程教程(第2部分:控制端协议拆解与机器人逻辑调试)

作者&#xff1a;那个写了个机器人结果自己被踢出房间的开发者 游戏逻辑房间结构参考界面 从这张图我们能看出&#xff0c;该组件按功能结构细分为多个房间&#xff0c;每个房间底注、准入标准不同&#xff0c;对应的控制模块也有层级区分。常规来说&#xff0c;一个“互动房间…

[特征工程]机器学习-part2

1 特征工程概念 特征工程:就是对特征进行相关的处理 一般使用pandas来进行数据清洗和数据处理、使用sklearn来进行特征工程 特征工程是将任意数据(如文本或图像)转换为可用于机器学习的数字特征,比如:字典特征提取(特征离散化)、文本特征提取、图像特征提取。 特征工程步骤…

[数据库之十一] 数据库索引之联合索引

执行数据库查询时&#xff0c;通常查询条件是多对个属性进行判断和约束&#xff0c;对于这种类型的查询&#xff0c;如果存在多个索引则使用多个索引&#xff0c;或者使用建立在多属性搜索码上的索引&#xff0c;这样能提高查询效率。 一、使用多个单码索引 假设数据表 instruc…

增强学习(Reinforcement Learning)简介

增强学习&#xff08;Reinforcement Learning&#xff09;简介 增强学习是机器学习的一种范式&#xff0c;其核心目标是让智能体&#xff08;Agent&#xff09;通过与环境的交互&#xff0c;基于试错机制和延迟奖励反馈&#xff0c;学习如何选择最优动作以最大化长期累积回报。…

PaddlePaddle 和PyTorch选择与对比互斥

你遇到的错误信息如下&#xff1a; RuntimeError: (PreconditionNotMet) Tensors dimension is out of bound.Tensors dimension must be equal or less than the size of its memory.But received Tensors dimension is 8, memorys size is 0.[Hint: Expected numel() * Size…

vison transformer vit 论文阅读

An Image is Worth 16x16 Words 20年的论文看成10年的哈斯我了 [2010.11929] 一张图像胜过 16x16 个单词&#xff1a;用于大规模图像识别的转换器 --- [2010.11929] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 为什么transformer好训练&am…

依赖关系-根据依赖关系求候选码

关系模式R&#xff08;U, F&#xff09;, U{}&#xff0c;F是R的函数依赖集&#xff0c;可以将属性分为4类&#xff1a; L: 仅出现在依赖集F左侧的属性 R: 仅出现在依赖集F右侧的属性 LR: 在依赖集F左右侧都出现的属性 NLR: 在依赖集F左右侧都未出现的属性 结论1: 若X是L类…