Tagged: 数据库

0

关系型数据库进阶之数据管理

我们在前面已经介绍了客户端管理,查询管理,今天来介绍数据管理。 在这一步中,查询管理会执行相应的查询,这个时候就需要从表和index中得到数据了。它需要数据管理来获取数据,不过这里有两个问题: 关系型数据库使用的是transaction的模式,所以你不能够在任何时候都得到数据,因为同时可能有别人在使用或者修改数据。 数据的获取是数据库中所有操作最慢的操作,所以数据管理需要足够聪明,来把数据保存在内存buffer中。 本文我们就会来讨论关系型数据库是如何处理这两个问题的。 Cache管理 就像我们前面几篇文章提到的一样,数据库的瓶颈就在于磁盘I/O,所以为了改进性能,需要使用cache管理器。 Query的执行器并不是从文件系统直接获取数据,而是通过cache manager来请求数据。Cache manager有一个memory的cache,我们称之为buffer pool。显然动态地从cache请求数据会增加数据获取的速度。一般来说memory相比磁盘来说会快100到100K倍,当然这还取决于决定的硬件和读写方式。 但是这里就会有另外一个问题,就是cache manager需要在query执行之前就获取到相应的数据,否则就还需要访问磁盘来数据。 预获取 query执行器其实是知道它所需要的数据,因为它知道整个query的所有流程。基于此,我们可以让query执行器处理第一部分数据的时候,就要去cache manager去预加载第二部分的数据,然后当它处理第二部分的数据的时候,就让cache manager去预加载第三部分的数据,这样循环下去。 Cache manager会把所有的数据保存在它的buffer pool中,为了检查相关数据是否还需要,cache manager在所有的cache数据中加入了一个额外的信息(我们称之为latch)。 当然有时候query执行器也不知道它下面要什么数据,这个时候就会使用一些特殊的预加载(比如,query执行器要数据1,3,5,那么它很有可能在未来需要数据7,9,11)或者顺序获取(这种情况下,cache manager就继续加载磁盘中后面的数据)。 为了探测预获取的效率,数据库提供一个称之为buffer/cache hit ratio的指标,这个指标会显示当请求一个数据的时候,有多少次是可以直接在cache中获取而不需要访问磁盘。 但是另外一个问题就是memory的大小毕竟有效,所以假如要加载新的数据,那么就得去除一些旧的数据,而这些加载和去除都是需要磁盘以及网络I/O消耗的。假如有一个查询经常执行,那么我们就会频繁地加载和去除相关的数据,这显然是不太合理的,那该如何处理呢?现代的数据库使用一种称之为buffer替换的策略。 buffer替换策略 现代的数据库(至少SQL Server, MySQL, Oracle和DB2)基本都使用LRU算法。 LRU就是Least Recently...

0

关系型数据库进阶之查询优化二

在前面的文章中我们介绍了查询优化的基础,着重介绍的两个表的JOIN的优化。本文就来看看我们在实际中更常见到的多表JOIN的优化。 现在我们来假设有五个表进行join,我们需要从不同的表中得到一个人的不同信息,比如地址,mail,mobiles等等,简单的QUERY如下所示: 作为查询优化器需要找到最佳的查询数据的方法,这里有两个问题: 每一个join需要使用什么类型的JOIN?我们有三种可能的JOIN (Hash Join,merge  Join, Nested Join) 先做哪个JOIN再做哪个JOIN? 下面这个是一个简单的示意图,有四个表,三个JOIN的情况,显然五个表的情况会更加复杂。 好的,那我们该怎么做呢? 1)暴力解法 遍历所有的可能性,然后找到最佳的方法。在上面的例子中,每一种join有三个可能(HASH, MERGE, NESTED),对于给定顺序的JOIN就有3^4中可能,而JOIN的顺序也是不定的,四个JOIN其实有(2*4)!/(4+1)!种可能的排序,这样一来,这个五个表的JOIN有 3^4*(2*4)!/(4+1)!种可能。 也就意味着,有27216中可能的计划。假如说merge join有0,1,2 B+ tree index,那么这种可能性就变成210000种了。而这还只是一个简单的JOIN。 2)只试验一些计划,然后选择其中最好的 因为可能性太多了,那么我们随机选择其中一些,然后计算他们的cost,选择其中最好的。 3)应用一些规则,来减少可能的计划 这里通常有两种规则: 使用一些简单的逻辑规则去除一些没有用的可能性,只是说这种去除不是很多。比如“nested loop join的inner relation必须是最小的数据集“ 使用一些有侵略性的规则来减少可能性。比如“假如一个relation很小,那么使用nested loop而不使用merge join和hash join”...

0

关系型数据库进阶之查询优化

在前面几篇文章中,我们已经介绍了总体构架,客户端管理和查询管理。在查询管理中,有一个很重要的部分我们没有介绍,那就是查询优化,这也是本文所要介绍的内容。 所有的现代数据库都是基于cost进行优化的(Cost Based Optimization, CBO)。总体的思想就是看每一个操作的cost是多少,然后找出一个cost最小的路径来执行这些操作并获取结果。 本文会首先以最常的三种join为例来进行介绍,看看哪怕是简单的join,它背后的优化是如何进行工作的。在这些例子中,我们关注时间复杂度,这个其实和真实的数据库优化器的计算是有所不同的,它真实会关注CPU消耗,磁盘I/O消耗以及内存的需求。时间复杂度和CPU消耗其实是差不多的,我们这种懒人就直接使用时间复杂度来进行分析了。当然有时候我们还需要考虑磁盘的I/O消耗,因为很多时候真正的瓶颈就是在于磁盘I/O而不是CPU的使用率。 JOIN的操作 我们会来看三个最常见的join操作,merger Join, Hash Join以及Nested Loop Join。在正式开始之前,我们来引入两个名词,outer relation和inner relation,很简单outer relation就是join左边的数据集,inner relation就是join右边的数据集。比如A JOIN B, 我们把A称之为outer relation而B称之为inner relation。并且假设outer relation有N个元素,inner relation有M个元素。我们可以很容易知道A JOIN B和B JOIN A其实是不太相同的。 Nested loop join Nested loop join是最简单的一种情况...

0

关系型数据库进阶之客户端管理

在上一篇文章中我们介绍了数据库的总体架构,今天我们将和大家来一起分析一下其核心组件中的重要组成部分:客户端管理。 客户端管理,顾名思义它是用来处理和客户端之间的信息交互的。客户端可以是一个web的server或者一个终端的用户/应用。客户端可以通过各种不同的方式来访问数据库,比如JDBC, ODBC, OLE-DB等等。 当连接数据库的时候,会执行下面这些步骤: 客户端管理首先检查你的权限和认证,看你是否有相应的访问数据库的权限。这些权限都是通过DBA来设置的。 然后,它会检查看是否有可用的进程(或者线程)来管理你的query 再检查看相应的数据库是否处于很重的负载情况下。 得到相应的资源,这里会有一个timeout,假如一定时间还没有得到资源,则会timeout,并且关闭相应的连接以及返回一个可读的错误信息。 发送query到相应的query manager,你的query就被执行了 Query 的过程并不是说全部返回,可能是一部分一部分返回的,所以它会把部分的返回值保存在一个buffer中,并且开始把它们分步发送回客户端。 假如有什么问题,它会断开连接,然后给出一个清晰的错误解释,并释放相关的资源 这就是整个数据库的客户端管理流程,其实还是蛮简单的,下一篇我们将会具体介绍更为核心的Query Manager部分。 参考文章:http://coding-geek.com/how-databases-work/

0

关系型数据库进阶之总体架构

一提到关系型数据库,我们可以看到它被在各个地方使用。有很多不同的关系型数据库,从最小的SQLite到复杂的Teradata。有很多文章在介绍如何使用数据库,但是很少有问题去深入地介绍它是如何工作的。假如你搜索“关系型数据库是如何工作的”这样的关键词,你会发现很少有问题进行深入详细的介绍。有时候,我们不禁会问,关系型数据库是不是太旧了,以至于都没有什么人来深入分析其中的内容? 作为一个开发者,我们需要有一点好奇心去深入看看我们每天使用的数据库内部是怎么样,假如你一直没有时间或者机会去深入了解其中的原理,那么本文将会是你的一个很好的选择。本文之所以称之为“进阶”是因为我们不会介绍如何去使用一些Query,而是假设你已经有了这些基础的知识,我们更注重其中的机理讲解。 一个数据库其实是信息的集合,而这个集合是可以很方便地访问和修改的。假如往简单的方面来想,那么它就是一系列的文件。事实上,最简单的数据库,比如SQLite其实就是一堆文件。当然SQLite又不是简简单单的一堆文件,因为它允许你: 使用transaction来保证数据的安全和连贯 能够很快的处理数据,哪怕是很大的百万量级的数据 总得来说,一个数据库可以由下图几个部分组成: 从这张图可以看出,总得核心有一下几个部分: 核心的组件: 进程管理: 很多数据库都有一个进程/线程池需要管理。更有甚者,为了做到纳秒级的效率,很多数据库都使用他们自己的线程而不是系统的线程。 网络管理:网络的I/O其实对数据库来说很重要,尤其是在分布式数据库中更为明显。这也是为什么很多数据库都有他们自己的管理者。 文件系统管理:数据库的第一个瓶颈就在于磁盘的I/O。需要一个文件系统管理来处理相关的内容,甚至取代系统的文件系统。 内存管理:为了避免磁盘I/O的损失,就需要大量的RAM。随之而来的就是,当你处理大量的内存的时候,你就需要一个高效的内存管理。尤其是你同时有很多query在使用内存的时候。 安全管理:主要管理用户的认证。 客户端管理:管理客户端的连接 工具: 备份管理:保存和还原数据库。 恢复管理:在数据库奔溃后能够以一致的状态启动数据库。 监测管理:记录数据的运行log,并且提供相应的检测工具。 Admin管理:用于存储元数据比如表的名字,结构,以及管理数据库,schema,表格空间等等。 Query管理: Query的解析:检查一个query是否有效 Query的重写:预先优化一个query Query的优化:优化一个query Query的执行:编译和执行query 数据的管理: Transaction管理:处理transcation cache的管理:在使用数据在前把数据放到内存,以及在写到磁盘之前把数据放到内存中 数据访问的管理:如何从磁盘访问数据 本文就从宏观介绍了数据库的组成部分,我们将在后面的文章中来分别主要介绍以下的内容: 客户端管理 查询管理 数据管理 参考文章:http://coding-geek.com/how-databases-work/