第十讲 Query Execution Part 1

news2024/11/15 20:02:40

1 处理模型【Processing Model】

DBMS 的处理模型【Processing Model】定义了系统如何执行【execute】查询计划【Query Plan】。

  • 针对不同的工作负载进行不同的权衡。

方法1:迭代器模型【Iterator Model】
方法2:物化模型【Materialization Model】
方法3:矢量化/批处理模型【Vectorized / Batch Model】

1.1 迭代器模型

迭代器是最简单的模型。他是一种自顶向下的方法。

每个查询计划【Query Plan】的(物理)操作符【Operator】都实现一个 Next() 函数。

  • 在每次调用时,操作符返回单个元组(需要注意的是,这个元组可以是关于列的一个子集,也可以是 Record ID),如果没有更多元组,则返回 eof 标记。
  • 操作符实现一个循环,即查询计划树中的父操作符在在其子节点的操作符上调用 Next() 来检索其输出元组,然后处理它们。

每个操作符的实现还具有 Open() 和 Close() 函数,它们类似于构造函数和析构函数,但这是用于操作符的罢了。
迭代器模型也称为火山模型【Volcano Model】或管道模型【Pipeline Model】。

如今大多数 DBMS 都使用这种方法,,它使得元组流水线【pipeling】成为可能。
许多运算符必须阻塞,直到他们的子操作符发出所有元组,赭红操作符也被称为 Pipeline Breaker:

  • 连接【Joins】,
  • 子查询【Subqueries】
  • 排序【Order By】

使用这种方法可以轻松进行输出控制。比如我们在查询【Query】中添加 LIMIT 10 子句,那么点那个我们的根操作符在迭代了 10 次后就可以停止了,我们不需要再继续调用 Next 了。

迭代器的约束是:我们一次只能处理一个元组,我们通过 Next 获取一个元组,然后可能会去做一些成本很高的操作,如果我们可以批量处理,那么就可以摊销很多的成本。

1.2 物化模型

物化模式是一种自底向上的方法。当父操作符调用子操作符时,他总是生成他可以生成的所有结果,然后上推给它的父擦作符。

每个操作符一次处理所有输入,然后一次发出所有输出。

  • 操作符将其输出“物化”为单个结果。
  • DBMS 可以下推提示【push down hints】(例如 LIMIT)以避免扫描太多元组。
  • 可以发送物化后的行或者单个行。

输出可以是整个元组 (NSM) 或列的子集 (DSM)。

在该模型下,我们经常会用到内链【inline】,比如图中的 S 表假设有亿万数据,我们将所有元组加载到内存,然后一次返回给父操作符,这种方法太愚蠢了,因此我们会将某些操作符进行内联。

物化模型更适合 OLTP 工作负载,因为查询一次仅访问少量元组。

  • 更低的执行/协调开销。
  • 更少的函数调用/操作符调用

但是不适合具有大量中间结果的 OLAP 查询。 

1.3 矢量模型

矢量模型就像迭代器模型一样,每个运算符都实现一个 Next() 函数,但是每个操作符发出一批元组而不是单个元组。

  • 每个运算符在内部作循环中,一次处理多个元组来加快速度(由于我们一次可以看到所有的数据,我们可以做一些矢量化操作,比如SIMD)
  • 批次的大小可能因硬件或查询属性而异

矢量化模型非常适合 OLAP 查询,因为它大大减少了每个操作符的调用次数,并使得操最符更轻松地使用矢量化 (SIMD) 指令来处理批量元组。 

1.4 PLAN PROCESSING DIRECTION

方法1:自上而下:

  • 从根开始,从其子节点“提取”数据。
  • 元组总是通过函数调用传递。

方法2:自下而上

  • 从叶节点开始,将数据推送到其父节点。
  • 允许对管道中的缓存/寄存器进行更严格的控制。
  • 更适合动态查询重新优化。

但是,大多数系统都是自顶而下的。

2 访问方法【Access Method】

访问方法是 DBMS 访问存储在表中的数据的方式,它在关系代数中未定义。

三种基本的访问方法:

  • 顺序扫描【Sequential Scan】
  • 索引扫描【 Index Scan】(许多变体)。
  • 多索引扫描【Multi-Index Scan】

2.1 顺序扫描【Sequential Scan】

对于表中的每一页【Page】:

  • 从缓冲池中检索它
  • 迭代每个元组并检查是否需要包含它

DBMS 维护一个内部游标,用于跟踪它检查过的最后一个页【Page】/槽【SLot】。、

这几乎总是 DBMS 在执行查询时可以做的最糟糕的事情,但它有时候可能是唯一可用的选择(比如当我们没有任何索引时)。
顺序扫描的优化:

  • 预取【Prefetching】
  • 缓冲池绕过【Buffer Pool Bypass】
  • 并行化【Parallelization】
  • 堆聚簇【Heap Clustering】
  • 延迟物化【 Late Materialization】
  • 数据跳过【Data Skipping】
数据跳过

方法1:近似查询【Approximate Queries】(有损)

  • 对整个表的采样子集执行查询以产生近似结果。
  • 示例:BlinkDB、Redshift、ComputeDB、XDB、Oracle、Snowflake、Google BigQuery、DataBricks

方法2:区域地图【Zone Map】(无损)

  • 预先计算每页的列式聚合【Aggregation】,DBMS 首先检查区域地图【Zone Map】来决定是否要访问该页【Page】。
  • 需要在页面大小与过滤器效能之间进行权衡,因为页面越大,数据也就越多,如果在一个有百万数据的大页上,我们根据区域地图算出需要访问该页,但是该页中可能只有一条数据满足查询条件,但是我们不得不扫描完整的页。
  • 示例:Oracle、Vertica、SingleStore、Netezza、Snowflake、Google BigQuery

2.2 索引扫描【 Index Scan】

DBMS 选择一个索引来查找查询【Query】所需的元组。
使用哪个索引取决于(所有这些都是后面章节里会讲,大概是第12讲):

  • 索引包含哪些属性【attribute】
  • 查询【Query】引用哪些属性【attribute】
  • 属性【attribute】的值域
  • 谓词组合【Predicate composition】
  • 索引是否有唯一键或非唯一键

假设我们有一个包含 100 个元组和两个索引的表:
→ 索引1:age
→ 索引2:dept

SELECT * FROM students

WHERE age < 30

AND dept = 'CS'

AND country = 'CHINA'

场景1:30岁以下的有99人,但是CS部门只有2人。 

在该场景下,我们希望可以选择 dept 索引,因为他的选择性更好,可以顾虑更多的数据

场景1:30岁以下的有 2人,但是CS部门有99人。 

在该场景下,我们希望可以选择 age 索引,因为他的选择性更好,可以顾虑更多的数据

2.3 多索引扫描【Multi-Index Scan】

如果 DBMS 可以在一个查询【Query】中使用多个索引:

  • 使用每个匹配的索引计算 Record ID 的集合。
  • 根据查询【Query】的谓词,来组合这些集合(并集与交集)
  • 检索记录并应用剩余的谓词

实现的数据库:

  • DB2 多索引扫描
  • PostgreSQL 位图扫描
  • MySQL 索引合并

SELECT * FROM students

WHERE age < 30

AND dept = 'CS'

AND country = 'CHINA'

继续复用前面的 age 和 dep 的例子:

  • 我们可以使用第一个检索 idx_age 来匹配满足 age < 30 的 Record ID
  • 然后使用第二个检索 idx_dep 来匹配满足 dept = 'CS' 的 Record ID,
  • 取它们 的交集
  • 检索记录,并检查 country = 'CHINA'

可以使用位图【Bitmap】或哈希表【Hash Table】有效地完成集合交集。

3 修改查询【Modification Query】

修改数据库的操作符(INSERT、UPDATE、DELETE)需要负责修改目标表【table】及其索引【index】,约束检查可以立即在操作符内部发生,也可以推迟到稍后的查询【Query】/事务【Transction】中。


这些运算符的输出可以是 Record ID 或元组数据(即 RETURNING)。

UPDATE/DELETE:

  • 子操作符传递目标元组的 Record ID
  • 必须追踪每一个先前看到过的元组(下面例子里会讲,这也是万圣节问题的解决方案)。

INSERT:

  • 选择1 :在操作符内部物化元组
  • 选择2:操作符插入从子操作符传入【Pass In】的任何元组。

例子:

1️⃣ 假设我们有一张perople表,表中记录了薪水

2️⃣ 现在我想对所有薪水小于 1100 的人作一次 100 元的薪水普调,那么现在我的更新操作符会调用它的子操作符的 Next 方法,该子操作符执行一个索引扫描,以超出所有薪水小于 1100 的工人

 

3️⃣ 在索引扫描中,我们跟随游标遍历数据,并将满足条件的元组返回给父操作符

4️⃣ 然后父操作符将它从索引内删除,然后插入一条更新后的索引


5️⃣ 然后索引游标继续滑动,但是我们会查到刚才插入的那条数据

这就是著名的万圣节问题【HALLOWEEN PROBLEM】,即:更新操作更改元组的物理位置,导致扫描操作符多次访问该元组的异常。

  • 可能发生在聚簇表或索引扫描上。

IBM 研究人员于 1976 年万圣节在 System R 上工作时首次发现。
解决方案:跟踪每个查询【QUery】中修改的 Record ID。 

4 表达式评估【Expression Evaluation】

DBMS 将 WHERE 子句表示为表达式树【Expression Tree】。我们前面看到查询计划【QUery Plan】是一颗关于操作符的数,在每个操作符内部依然可以是树结构。

表达式树中的节点代表不同的表达式类型:

  • 比较(=、<、>、!=)
  • 合取 (AND)、析取 (OR)
  • 算术运算符(+、-、*、/、%)
  • 常数值
  • 元组属性引用【Tuple Attribute Reference】

例子:

1️⃣ 下面是我们要执行的 Prepared 语句,我们调用execute执行它

 2️⃣ 下面是该SQL中的表达式树:

以这种方式评估谓词的速度其实很慢,DBMS 遍历树,对于它访问的每个节点,它必须弄清楚操操作符需要做什么。

我们来考虑这个谓词:WHERE S.val=1

更好的方法,或者说是优化吧,就是直接计算表达式,回想一下 JIT 编译,Postgre 中就有这个特性,它会将表达式部分内联编译(set jit = 'on')。

5. Schedule

到目前为止,我们基本上已经从数据流【data flow】的角度了解了查询处理模型【query processing model】。
控制流【conrol flow】隐含在处理模型【processing model】中。 我们可以使用调度程序【scheduler】使控制流更加明确。
数据库论文中通常不会讨论查询调度程序【scheduler】。 我们将看看 Quickstep(学术)项目中做了什么。 基于允许数据流和控制流之间的频繁切换。

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

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

相关文章

linux虚拟机上安装,使用以及远程连接mysql

1. 安装mysql 5.7 1) 首先更新软件源 sudo apt-get update 2) 安装MySQL数据库软件 ​ sudo apt-get install mysql-server 3) 安装MySQL数据库管理软件​ sudo apt-get install mysql-client 4) 安装MySQL数据库客户端&#xff0c;用户访问数据库 sudo apt-get install…

JAVA—抽象—定义抽象类Converter及其子类WeightConverter

同样&#xff0c;我们由这道题引出抽象类&#xff0c;抽象方法这个概念。 按下面要求定义类Converter及其子类WeightConverter 定义抽象类&#xff1a;Converter&#xff1a; 定义一个抽象类Converter&#xff0c;表示换算器&#xff0c;其定义的如下&#xff1a; 一个私有…

HarmonyOS实战开发DLP-如何实现一个安全类App。

介绍 本示例是一个安全类App&#xff0c;使用ohos.dlpPermission 接口展示了在eTS中普通文件加密受限的过程。 效果预览 使用说明: 1.启动应用后点击“”按钮可以添加一个普通文件; 2.长按点击加密按钮&#xff0c;出现加密权限弹窗&#xff0c;选择需要设置的权限并点击确定…

【C语言】_文件类型,结束判定与文件缓冲区

目录 1. 文本文件和二进制文件 2. 文件读取结束的判定 3. 文件缓冲区 1. 文本文件和二进制文件 根据数据的组织形式&#xff0c;数据文件被称为文本文件或二进制文件&#xff1b; 数据在内存中以二进制的形式存储&#xff0c;如果不加转换地输出到外存&#xff0c;就是二进…

蓝桥杯刷题-13-子矩阵-二维滑动窗口 ಥ_ಥ

给定一个 n m &#xff08;n 行 m 列&#xff09;的矩阵。 设一个矩阵的价值为其所有数中的最大值和最小值的乘积。求给定矩阵的所有大小为 a b &#xff08;a 行 b 列&#xff09;的子矩阵的价值的和。 答案可能很大&#xff0c;你只需要输出答案对 998244353 取模后的结果。…

Redis 的主从复制、哨兵和cluster集群

目录 一. Redis 主从复制 1. 介绍 2. 作用 3. 流程 4. 搭建 Redis 主从复制 安装redis 修改 master 的Redis配置文件 修改 slave 的Redis配置文件 验证主从效果 二. Redis 哨兵模式 1. 介绍 2. 原理 3. 哨兵模式的作用 4. 工作流程 4.1 故障转移机制 4.2 主节…

Java开发测试(第一篇):Java测试框架JUnit5

目录 1.基本介绍 2.maven中安装JUnit5 3.使用 4.JUnit5命名规则 5.JUnit5常用注解 6.JUnit5断言 7.JUnit5多个类之间的继承关系 8.JUnit5参数化 &#xff08;1&#xff09;使用场景&#xff1a; &#xff08;2&#xff09;使用前需在pom.xml文件中导入依赖 &#xff…

海纳斯删除广告位

找到文件 vim /var/www/html/home.php 删除代码段 <div class"adleft" id"adleftContainer"><button onclick"closeAd()">关闭</button><a href"https://www.ecoo.top/ad.html" target"_blank">&l…

怀俄明探空站数据解算PWV和Tm

1. Matlab 获取代码可关注公众号WZZHHH回复&#xff08;怀俄明探空站数据解算PWV和Tm&#xff09;&#xff0c;或者咸鱼关注&#xff1a;WZZHHH123 怀俄明探空站数据解算PWV和Tm&#xff1a; 有关 Matlab 获取代码可关注公众号WZZHHH回复&#xff08;怀俄明多线程下载&#…

最新怎么订阅OnlyFans上喜欢的博主,详细教程

大家好&#xff0c;本文教大家如何用虚拟信用卡在 Onlyfans 订阅&#xff0c;链接在浏览器打开地址https://bewildcard.com/i/GPT310&#xff0c;虚拟卡开好之后&#xff0c;用支付宝充值就可以进行订阅OnlyFans平台的博主了。 什么是OnlyFans&#xff1f; OnlyFans 是一个提…

毅速解析:金属3D打印模具工件性能如何?

3D打印技术&#xff0c;在模具随形水路、异形模具制造以及模具排气结构等方面的独特优势&#xff0c;已成为模具升级的重要技术方向&#xff0c;并受到众多注塑、压铸等模具行业的青睐。 然而&#xff0c;面对这一新兴技术&#xff0c;不少人不免心生疑虑&#xff1a;3D打印技术…

【c++练习】求3个长方柱的体积

【问题描述】编写一个基于对象数组的程序&#xff0c;用成员函数实现多个功能&#xff0c;求3个长方柱的体积。要求用成员函数实现以下功能&#xff1a; 1、由键盘分别输入3个长方柱的长、宽、高&#xff1b; 2、计算长方柱的体积&#xff1b; 3、输出3个长方柱的体积。 【…

MySQL基础【语句执行顺序】

一个SQL语句它的执行顺序对于我们思考题意有着很重要的关系 题意就是&#xff1a;找出哪些只逛超市不买单的人&#xff08;买单0元也算哦&#xff0c;可能是使用的是代金券吧&#xff09; 看到此题关键找出两个数据 参观过的人 和 买单的人 他们的差就是白嫖的人&#xff08;支…

C语言分支语句

一、什么是语句 C语句可分为以下五类&#xff1a; 表达式语句 函数调用语句 控制语句 复合语句 空语句 本周后面介绍的是控制语句。 控制语句用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式&#xff0c;它们由特定的语句定义符组成&#xff0c;C语 言有…

远程过程调用(远程调用)

远程过程调用&#xff08;远程调用&#xff09; 1、什么是分布式计算 在计算机科学中&#xff0c;分布式计算&#xff08;英语&#xff1a;Distributed computing&#xff09;&#xff0c;又译为分散式运算。这个研究领域&#xff0c;主要研究分布式系统&#xff08;Distribu…

什么是MQ ?为什么用MQ?

什么是MQ&#xff1f; MQ(message queue)&#xff08;消息队列&#xff09;&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;只不过队列中存放的内容是message而已&#xff0c;还是一种跨进程的通信机制&#xff0c;用于上下游传递消息…

春招-实战项目冲刺直播课

春招-实战项目冲刺直播课 CCtalk 丰富多元的综合内容平台-专业的知识分享与在线教育平台https://www.cctalk.com/m/group/91161801

解决win7作为虚拟机无法复制粘贴共享文件的问题

win7作为虚拟机经常会出现无法与主机的剪切板共享、文件共享。 归根结底是win7虚拟机里面没有安装VMware Tools 能够成功安装vmware tools的条件&#xff1a; 1&#xff09;win7版本为win7 sp1及以上 2&#xff09;安装KB4490628&#xff0c;KB4474419补丁 因此下面来详细介绍…

QA测试开发工程师面试题满分问答9: Python中内存管理的概念、原理、使用

概念原理 Python中的内存管理是由解释器自动处理的&#xff0c;它使用引用计数和垃圾回收机制来管理内存。以下是Python内存管理的一些关键概念、设计原理和最佳实践&#xff0c;以帮助您高效使用和管理内存&#xff1a; 引用计数&#xff1a;Python使用引用计数来追踪对象的引…

c++的学习之路:8、内存管理与模板

一、 C/C内存分布 首先在c语言的动态内存管理中我知道了代码是如何存储数据的&#xff0c;然后c是根据c语言底层变化来的&#xff0c;那么c语言的内存管理就是适用c的内存管理&#xff0c;在c语言中程序是分为几个部分存储&#xff0c;例如在栈堆等等&#xff0c;他们的分布如…