原标题:How does a relational database work
作者:Christophe
http://coding-geek.com/how-databases-work/
ps:翻译这篇文章,是为了强迫自己看得更仔细,同时将好东西分享出来.现在技术底蕴不厚,写不出好的文章,没关系,翻译大佬的文章也是一条成长之路
前言
每当谈起关系型数据库,我总是觉得缺了点什么。他们无处不在。有很多不同的数据库:从小巧犀利的SQLite 到强力支持万亿级数据的数据库。但是解释数据库如何工作的文章却寥寥无几。你可以通过google搜索“how does a relational database work”来看看相关结果到底少到什么地步。并且这些文章都很短。目前,如果你去搜索时下比较流行的技术(Big Data, NoSQL or JavaScript),你会发现很多文章都深入地解释了这些技术背后的原理。
除开在大学课程上,研究论文和书本上,关系型数据库探讨是否显得太过时,太无聊?
作为一个开发者,我讨厌用一些自己不懂的技术。并且,数据库已经被使用超过40年了,这不是没有道理的。过去几年,我花费了数百个小时的时间才搞懂这些每天都在用的黑匣子。关系型数据库基于可用和可重用的概念,所以很有意思。如果你对了解数据库有兴趣却没有太多时间去深入发掘背后的原理,你可以看下这篇文章。
这篇文章的主题很明确,不是去教你如何使用数据库。因此,为了保证你能读懂这篇文章,你至少要会简单的连接查询和基础的CRUD操作。其他的我会在文章中解释。
我会以时间复杂度等计算机科学的东西开始,我知道你们有些人比较讨厌这个概念,但是,不搞清楚这些概念,你很难彻底弄清数据库内部原理。这个话题比较宽泛,我会将焦点放在数据库处理SQL查询,这是我个人认为很有必要的。我只会介绍数据库的基本概念,目的是在文章结束后,你会对引擎下发生的事情有一个更好的了解。
这是一篇很长的技术性文章,并且包含了很多算法和数据结构。你需要花费一些时间来读它。一些概念比较晦涩难懂,你可以跳过查看结论。
为了让你更容易读懂,这篇文章分为三个部分。
- 低级和高级数据库组件的概述
- 查询优化过程概述
- 事务和缓冲池管理的概述
基础回顾
很久以前,开发者想要明确知道他们设计的程序需要操作的步数。他们想了解他们的算法和数据结构,这对他们的程序提高cpu和内存的使用效率很重要。
在这一部分,我会解释一些必须的数据库基本概念以及数据库索引的概念。
O(1) vs O(n2)
现在,大多数开发者并不关心时间复杂度…这没啥问题。
但是,如果你想处理大量的数据(不是指上千这样的级别),或者是追求毫秒级的处理,那么理解这些概念就显得异常重要。也许你已经猜想到了,数据库必须同时处理这两种场景。我不会占用你太多时间,现在就来了解下这个想法。这会帮助我们理解基于成本优化的概念。
时间复杂度概念
时间复杂度常常被用来衡量一个算法处理给定规模的输入数据所耗费的时间。为了描述这个时间复杂度,计算机科学家使用大O表示法。此表示法与一个函数一起使用,该函数描述算法对给定规模的输入数据需要多少操作。
例如,当我说“此算法在O(some_function())”时,这意味着对于一定规模的数据,算法需要some_function(a_certain_amount_of_data)操作来完成其工作。
我们不关心数据量的多少。我们关心的是伴随着数据规模的增长,所耗费操作数的增长方式。时间复杂度不是用来算具体耗费操作数的,它反映了变化的趋势。
在此图中,你可以看到不同类型复杂度的演变。 我使用对数刻度来绘制它。 换句话说,数据的规模从1增加到10亿。 我们可以看到:
- O(1)或常数复杂度随数据规模增加保持不变(否则也不会被称作常数复杂度)
- O(log(n))即使有数十亿数据规模,也能保持在较低的水平
- 最糟糕的复杂度是O(n2) ,耗费的操作数随着数据规模增加而爆发式增长
- 其他两种复杂度增长也是很迅速的
例子
当数据规模很小的时候,O(1)和O(n2)的差距可以忽略不计。假定我们有个算法需要处理2000个元素时。
- O(1)算法将花费您1次操作
- O(log(n))算法将花费你7次操作
- O(n)算法将花费你2000次操作
- O(n*log(n))算法将花费你14 000次操作
- O(n2)算法将花费你4 000 000次操作