当前位置:首页 » 个人博客 » 正文

关系数据库是如何工作的(篇章3)

 人参与  2022年11月20日 13:14  分类 : 个人博客  点这评论

数据库是信息的集合,可以很容易地访问和修改。但是一堆简单的文件也可以做到这一点。事实上,像SQLite这样最简单的数据库无非就是一堆文件。但是SQLite是一组精心制作的文件,因为它允许您:

  • 使用确保数据安全一致的事务
  • 快速处理数据,即使您正在处理数百万的数据

 

更一般地说,数据库可以看做下图:

global overview of a database

在写这一部分之前,我已经阅读了多本书/论文,每一个来源都有其表示数据库的方式。所以,不要太关注我是如何组织这个数据库的,也不要太关注我是如何命名这些过程的,因为我做了一些选择来适应本文的计划。重要的是不同的组成部分;总的想法是一个数据库被分成多个相互交互的组件.

核心组件:

  • 流程经理

    :许多数据库都有一个

    进程/线程池

    这需要管理。此外,为了获得纳秒,一些现代数据库使用自己的线程,而不是操作系统线程。
  • 网络管理员

    :网络I/O是一个大问题,尤其是对于分布式数据库。这就是为什么有些数据库有自己的管理器。
  • 文件系统管理器磁盘I/O是数据库的第一个瓶颈

    。拥有一个能够完美处理操作系统文件系统甚至替换它的管理器是非常重要的。
  • 内存管理器

    :为了避免磁盘I/O损失,需要大量的ram。但是如果你处理大量的内存,你需要一个高效的内存管理器。尤其是当您同时有许多使用内存的查询时。
  • 安全经理

    :用于管理用户的认证和授权
  • 客户经理

    :用于管理客户端连接

工具:

  • 备份管理器

    :用于保存和恢复数据库。
  • 恢复管理器

    :用于在中重新启动数据库

    相干态

    撞车后
  • 监控经理

    :用于记录数据库的活动,并提供监控数据库的工具
  • 行政经理

    :用于存储元数据(如表的名称和结构)并提供管理数据库、模式、表空间等的工具

查询管理器:

  • 查询分析器

    :检查查询是否有效
  • 查询重写器

    :预优化查询
  • 查询优化器

    :优化查询
  • 查询执行器

    :编译和执行查询

数据管理器:

  • 事务管理程序

    :处理交易
  • 缓存管理器

    :在使用数据之前将数据放入内存,在将数据写入磁盘之前将数据放入内存
  • 数据访问管理器

    :访问磁盘上的数据

 

在本文的其余部分,我将重点介绍数据库如何通过以下过程管理SQL查询:

  • 客户经理
  • 查询管理器
  • 数据管理器(在这一部分中,我还将包括恢复管理器)

 

客户经理

client manager in databases

客户端管理器是处理与客户端通信的部分。客户端可以是(web)服务器或最终用户/最终应用程序。客户端管理器提供了通过一组众所周知的API访问数据库的不同方法:JDBC、ODBC、OLE-DB …

它还可以提供专有的数据库访问API。

 

当您连接到数据库时:

  • 经理首先检查你的

    证明

    (您的登录名和密码),然后检查您是否拥有

    授权

    使用数据库。这些访问权限由您的DBA设置。
  • 然后,它检查是否有一个进程(或线程)可以管理您的查询。
  • 它还检查数据库是否负载过重。
  • 它可以等待片刻来获得所需的资源。如果等待超时,它将关闭连接并给出一个可读的错误消息。
  • 然后它

    将您的查询发送到查询管理器

    您的查询会得到处理
  • 因为查询处理不是“要么全有,要么全无”的事情,一旦从查询管理器获得数据,它就

    商店 部分结果在缓冲区中并开始发送

    给你。
  • 如果有问题,它会停止连接,给你一个

    可读的解释

    并释放资源。

 

查询管理器

query manager in databases

这就是数据库的威力所在。在这一部分,一个写得不好的查询被转换成一个快的可执行代码。然后执行代码,并将结果返回给客户端管理器。这是一个多步骤的操作:

  • 首先是查询

    从语法上分析

    看看它是否有效
  • 就在那时

    重写

    删除无用的操作并添加一些预优化
  • 就在那时

    最佳化的

    以提高性能,并转化为执行和数据访问计划。
  • 那么计划是

    编辑

  • 最后,它

    执行

在这一部分,我不会过多谈论最后两点,因为它们不太重要。

 

读完这一部分,如果你想更好地理解,我推荐你阅读:

  • 基于成本优化的最初研究论文(1979年):

    关系数据库管理系统中的访问路径选择

    。这篇文章只有12页,以计算机科学的一般水平是可以理解的。
  • 这是一篇非常好的深入的关于DB2 9。x优化查询

    这里

  • 关于PostgreSQL如何优化查询的非常好的演示

    这里

    。这是最容易理解的文档,因为它更像是“让我们看看PostgreSQL在这些情况下给出了什么样的查询计划”而不是“让我们看看PostgreSQL使用的算法”。
  • 官方

    SQLite文档

    关于优化。它“容易”阅读,因为SQLite使用简单的规则。此外,这是唯一真正解释其工作原理的官方文档。
  • 关于SQL Server 2005如何优化查询的精彩演示

    这里

  • 关于Oracle 12c优化的白皮书

    这里

  • 2本书作者提供的查询优化理论课程

    数据库系统概念”这里

    和t

    这里

    。重点关注磁盘I/O成本的优秀读物,但需要有良好的CS水平。
  • 另一个

    理论课程

    我发现它更容易理解,但是它只关注连接操作符和磁盘I/O。

 

查询分析器

每个SQL语句都被发送到解析器,在那里检查语法是否正确。如果您在查询中犯了错误,解析器将拒绝该查询。例如,如果你写的是“选择…”而不是“选择…”,那么故事到此结束。

但这更深层。它还检查关键字的使用顺序是否正确。例如,在WHERE之前,SELECT将被拒绝。

然后,分析查询中的表和字段。解析器使用数据库的元数据来检查:

  • 如果

    表格存在

  • 如果

    田地(复数);场;域;字段

    表的存在
  • 如果

    操作

    对于字段的类型

    都是可能的

    (例如,不能将整数与字符串进行比较,不能对整数使用substring()函数)

 

然后它会检查您是否有授权读取(或写入)查询中的表。同样,这些对表的访问权限是由DBA设置的。

在解析过程中,SQL查询被转换成内部表示(通常是树)

如果一切正常,那么内部表示被发送到查询重写器。

 

查询重写器

在这一步,我们有了一个查询的内部表示。重写器的目标是:

  • 要预优化查询
  • 为了避免不必要的操作
  • 为了帮助优化器找到可能的最佳解决方案

 

重写器对查询执行已知规则的列表。如果查询符合规则的模式,则应用规则并重写查询。以下是(可选)规则的非详尽列表:

  • 视图合并:

    如果您在查询中使用视图,视图将使用视图的SQL代码进行转换。
  • 子查询展平

    :拥有子查询很难优化,因此重写器将尝试修改带有子查询的查询,以删除子查询。

例如

SELECT PERSON.*
FROM PERSON
WHERE PERSON.person_key IN
(SELECT MAILS.person_key
FROM MAILS
WHERE MAILS.mail LIKE 'christophe%');

将被替换为

SELECT PERSON.*
FROM PERSON, MAILS
WHERE PERSON.person_key = MAILS.person_key
and MAILS.mail LIKE 'christophe%';
  • 删除不必要的运算符

    :例如,如果您使用DISTINCT,而您有一个防止数据不唯一的UNIQUE约束,则DISTINCT关键字将被移除。
  • 冗余连接消除:

    如果您有两个相同的连接条件,因为一个连接条件在视图中被隐藏,或者如果通过传递性有一个无用的连接,它将被删除。
  • 常数算术评估:

    如果你写一些需要微积分的东西,那么在重写过程中它会被计算一次。例如,年龄> 10+2转换为年龄> 12,TODATE(“某个日期”)转换为日期时间格式的日期
  • (高级)分区修剪:

    如果您使用分区表,重写器能够找到要使用的分区。
  • (高级)实体化视图重写

    :如果您有一个与查询中的谓词子集匹配的实体化视图,重写器将检查该视图是否是最新的,并修改查询以使用实体化视图而不是原始表。
  • (高级)自定义规则:

    如果您有修改查询的自定义规则(如Oracle策略),则重写器会执行这些规则
  • (高级)Olap转换

    :分析/窗口函数、星形连接、汇总…也进行了转换(但我不确定这是由重写器还是优化器完成的,因为这两个过程非常接近,它必须依赖于数据库)。

 

这个重写的查询然后被发送到查询优化器,有趣的事情开始了!

 

统计数字

在我们了解数据库如何优化查询之前,我们需要讨论一下统计数字因为没有他们 数据库是愚蠢的。如果你不告诉数据库去分析它自己的数据,它就不会去做,并且会做出(非常)糟糕的假设。

但是数据库需要什么样的信息呢?

我不得不(简单地)谈谈数据库和操作系统是如何存储数据的。他们使用的最小单位叫做a 页,面,张,版或者一个块(默认为4或8千字节)。这意味着,如果你只需要1千字节,它将花费你一页。如果页面占用8kb,那么你将浪费7kb。

 

回到统计上来!当您要求数据库收集统计数据时,它会计算如下值:

  • 表格中的行数/页数
  • 对于表中的每一列:
    • 不同的数据值
    • 数据值的长度(最小值、最大值、平均值)
    • 数据范围信息(最小值、最大值、平均值)
  • 关于表索引的信息。

这些统计数据将帮助优化器估计 查询的磁盘I/O、CPU和内存使用情况。

每一列的统计数据都非常重要。例如,如果表PERSON需要连接两列:姓氏,名字。通过这些统计数据,数据库知道名字中只有1 000个不同的值,姓氏中有1 000 000个不同的值。因此,数据库将根据姓氏,名字而不是名字,姓氏来连接数据,因为它产生的比较更少,因为姓氏不太可能相同,所以大多数情况下,根据姓氏的前2(或3)个字符进行比较就足够了。

 

但这些都是基本统计。您可以要求数据库计算名为直方图。直方图是关于列内值分布的统计信息。例如

  • 最常见的值
  • 分位数

这些额外的统计数据将帮助数据库找到更好的查询计划。尤其是对于等式谓词(例如:其中年龄= 18)或范围谓词(例如:其中年龄> 10且年龄< 40),因为数据库将更好地了解这些谓词所涉及的行数(注意:这个概念的专业术语是选择性)。

 

统计数据存储在数据库的元数据中。例如,您可以看到(未分区的)表的统计信息:

  • 在Oracle的用户/所有/DBA _表和用户/所有/DBA _ TAB _列中
  • 在SYSCAT中。

    桌子

    SYSCAT。DB2的列.

 

统计数据必须是最新的。最糟糕的事情莫过于数据库认为一个表只有500行,而它有1 000 000行。统计数据的唯一缺点是计算它们需要时间。这就是为什么在大多数数据库中默认情况下它们不会被自动计算。有了数百万的数据,计算它们变得很困难。在这种情况下,您可以选择只计算基本的统计数据,或者计算数据库样本的统计数据。

例如,当我在一个项目中处理每个表中数以亿计的行时,我选择只计算10%的统计数据,这大大节省了时间。对于这个故事来说,事实证明这是一个糟糕的决定,因为Oracle 10G为特定表的特定列选择的10%有时与整体的100%相差很大(对于一个有1亿行的表来说,这种情况不太可能发生)。这个错误的统计数据导致查询有时需要8个小时,而不是30秒;一场寻找根源的噩梦。这个例子显示了统计数据的重要性。

 

注意:当然,每个数据库都有更高级的统计信息。如果你想知道更多,请阅读数据库的文档。也就是说,我试图理解统计数据是如何使用的,我找到的最好的官方文档是一个来自PostgreSQL.

本文由本站原创或投稿者首发,转载请注明来源!

本文链接:http://www.ziti66.com/net/html/164.html

本文标签:博客    

微信公众号:升级接入中

<< 上一篇下一篇 >>
为祖国加油
祖国加油,相信新的一年会更好...
为祖国加油
森林防火,人人有责。祖国加油...

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

搜索

网站分类

Tags列表

最新留言

++发现更多精彩++

    海内存知己,天涯若比邻。

黔ICP备2020011602号黔ICP备2020011602号-8
贵公安备52052602000222号

❤安全运行 Copyright © 2018-2023 李烨自媒体 版权所有.

本站采用创作共用版权 CC BY-NC-SA 3.0 CN 许可协议,转载或复制请注明出处