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.pswp.cn/web/79217.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79217.shtml
英文地址,請注明出處:http://en.pswp.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類…