数据库是如何获取并处理数据的

数据库 SQL Server
SQL是结构化查询语言(Structured Query Language)的简称,用户只需要通过SQL告诉数据库需要什么,至于怎么去做就是数据库管理系统(DBMS)需要考虑的问题。

SQL是结构化查询语言(Structured Query Language)的简称,用户只需要通过SQL告诉数据库需要什么,至于怎么去做就是数据库管理系统(DBMS)需要考虑的问题。

上篇文章《SQL语句处理》介绍了数据库执行的四个阶段,每个阶段都做了什么工作。今天这篇文章继续探讨数据库是如何获取到用户所需的数据。

如下所探讨的内容仅适用于Oracle单机环境,RAC环境稍有不同,不在本篇讨论范围内。

数据库的所有操作增、删、改、查都是在内存中完成的,为了处理数据,数据库首先需要将数据从磁盘读取到内存中,然后进行相应的操作。但是内存和磁盘的读写速度有着天壤之别。DDR4内存读写速度大概50G每秒(50000M),固态硬盘速度是300M每秒,是内存的二百分之一,机械硬盘的速度是100M每秒,是内存的五百分之一。为了解决两者之间的速度差的问题,诞生了缓存的概念。缓存的作用就是避免每次获取数据时都从缓慢的磁盘读取,而是将之前访问过的数据缓存在内存中,后续操作如果需要相同数据时,直接从内存获取,大大提升读取速度。

Oracle内存结构中有一个很重要的结构叫做DB Buffer Cache,DB Buffer Cache位于SGA中,正常系统中此部分内存占整个Oracle内存结构大绝大部分。如果DB Buffer Cache很大,几十G,甚至是几百G,每次在其中搜索所需的块是否存在,也需要很长的时间,因此,为了提高效率,Oracle将DB Buffer Cache划分为多个区域,每个区域称为一个工作集(workset),每个工作集又被划分为多个hash buckets,一个hash buckets管理着一个或多个数据块。为了保证数据的一致性,hash buckets访问是串行的,由相应的latch保护,只有获取到相应的latch的会话才能到hash buckets上搜索数据块。

1、查询语句的执行

假设有如下查询语句:

SELECT * FROM employees WHERE employee_id=199;

表employees表结构如下,employee_id是表的主键。

先看下上述sql语句的执行计划

首先根据索引EMP_EMP_ID_PK查找employee_id=199键,获取到键所对应的值ROWID,ROWID指向数据块的真实地址。通过ROWID获取数据块,获取到数据块后,再从数据块中获取符合条件的数据。在此过程中至少需要访问两个数据块(为了简化过程,忽略其他数据块),一个是键为199索引块,假设为100号块;另一个是索引块所指向的数据块,假设为1000号块。

前面缓存介绍中提到,为了提升数据的访问速度,Oracle会将访问过的数据块缓存到DB Buffer cache中,以备重复使用。因此上面获取100号索引块的时候,需要先到DB Buffer cache中查找100号索引块是否已存在,以减少昂贵的磁盘读。在搜索DB Buffer cache前,必须获取相应的latch后才能进行搜索。如果未获取到latch,此时会进入等待。待获取到latch后便可以对DB Buffer cache搜索。

如果100号索引块已存在于内存中,且没有会话正在修改数据块内容,直接访问内存中的数据块,获取键为199的数据。如果有会话正在修改此数据块内容,则需要通过undo数据和当前的数据块构造一个一致性读版本的数据块,来读取会话修改前的历史版本数据。

如果100号索引块不在内存中,首先判断是否有其他会话正在将100号索引块读入内存,如果是,则等待。否则通知后台进程将100号索引块从磁盘读入内存,在将100号索引块读入内存前,需要在内存中找到一块合适的空闲块,以便保存即将读入的100号索引块。搜索空闲块时同样需要获得latch。

如果内存中没有空闲的空间,则通知后台刷新进程刷新脏页,以腾出空闲空间。

如果内存中有空闲的空间,直接将100号索引块读入内存。获取到ROWID后,再去读取数据块,读取数据块的过程同读取索引块,读取到数据块后再从数据块中获取符合条件的行,返回给客户端。

2、DML语句执行

假设有如下更新语句:

UPDATE employees SET first_name='Hello',last_name='Kitty' WHERE employee_id=199;

update语句执行计划如下:

DML语句都存在相应的查询过程,因为只有查询到了所需要修改的数据,才能进行相应的操作。查询的过程大致与查询语句执行过程相同。但也有如下不同点:

获取latch时,如果是只读操作,多个会话可以同时获取相同的latch,如果是DML操作,则不可以同时获得。

只读操作多个会话可以同时读取同一个数据块,DML操作则不可以多个会话同时修改同一个数据块。

获取到数据块后进行相应的操作,并记录对应的undo信息和redo log信息,完成update操作。

责任编辑:华轩 来源: 今日头条
相关推荐

2018-08-09 12:23:31

数据库Oracle静默错误

2021-01-26 13:40:44

mysql数据库

2017-10-23 13:52:31

数据库硬件

2021-07-01 10:45:08

硬盘数据库性能

2011-05-26 14:43:49

ORACLE数据库异常处理

2011-04-07 15:47:28

MySQL数据库

2011-03-23 16:54:38

数据库联机处理

2022-11-14 18:23:06

亚马逊

2011-07-19 11:12:36

PHPMySQL数据库

2009-12-03 15:31:30

PHP获取显示数据库数

2010-05-31 15:23:02

MySQL数据库NUL

2021-02-23 14:56:12

数据库存储索引

2020-11-24 17:22:15

数据库MySQL技术

2011-06-30 16:57:03

数据压缩

2023-10-08 08:09:16

数据库性能服务器

2011-05-26 13:36:40

Oracle数据库时间处理

2010-07-15 17:28:50

SQL Server

2010-04-07 14:22:46

2010-04-09 14:37:08

Oracle数据库

2009-05-18 13:18:54

字符Oracle字符串
点赞
收藏

51CTO技术栈公众号