如果再有人问你数据库的原理,把这篇文章给他

一提到关系型数据库,我禁不住想:有些东西被忽视了 。关系型数据库无处不在,而且种类繁多,从小巧实用的 SQLite 到强大的 Teradata。但很少有文章讲解数据库是如何工作的 。你可以自己谷歌/百度一下『关系型数据库原理』,看看结果多么的稀少,而且找到的那些文章都很短 。现在如果你查找最近时髦的技术(大数据、NoSQL或JAVAScript),你能找到更多深入探讨它们如何工作的文章 。难道关系型数据库已经太古老太无趣,除了大学教材、研究文献和书籍以外,没人愿意讲了吗?

如果再有人问你数据库的原理,把这篇文章给他

文章插图
 
作为一个开发人员,我不喜欢用我不明白的东西 。而且,数据库已经使用了40年之久,一定有理由的 。多年以来,我花了成百上千个小时来真正领会这些我每天都在用的、古怪的黑盒子 。关系型数据库非常有趣,因为它们是基于实用而且可复用的概念 。如果你对了解一个数据库感兴趣,但是从未有时间或意愿来刻苦钻研这个内容广泛的课题,你应该喜欢这篇文章 。
虽然本文标题很明确,但我的目的并不是讲如何使用数据库 。因此,你应该已经掌握怎么写一个简单的 join query(联接查询)和CRUD操作(创建读取更新删除),否则你可能无法理解本文 。这是唯一需要你了解的,其他的由我来讲解 。
我会从一些计算机科学方面的知识谈起,比如时间复杂度 。我知道有些人讨厌这个概念,但是没有它你就不能理解数据库内部的巧妙之处 。由于这是个很大的话题,我将集中探讨我认为必要的内容:数据库处理SQL查询的方式 。我仅仅介绍数据库背后的基本概念,以便在读完本文后你会对底层到底发生了什么有个很好的了解 。
(关于时间复杂度 。计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间 。如果不了解这个概念建议先看看维基或百度百科,对于理解文章下面的内容很有帮助)
由于本文是个长篇技术文章,涉及到很多算法和数据结构知识,你尽可以慢慢读 。有些概念比较难懂,你可以跳过,不影响理解整体内容 。
这篇文章大约分为3个部分:
  • 底层和上层数据库组件概况
  • 查询优化过程概况
  • 事务和缓冲池管理概况
回到基础很久很久以前(在一个遥远而又遥远的星系……),开发者必须确切地知道他们的代码需要多少次运算 。他们把算法和数据结构牢记于心,因为他们的计算机运行缓慢,无法承受对CPU和内存的浪费 。
在这一部分,我将提醒大家一些这类的概念,因为它们对理解数据库至关重要 。我还会介绍数据库索引的概念 。
O(1) vs O(n^2)
现今很多开发者不关心时间复杂度……他们是对的 。
但是当你应对大量的数据(我说的可不只是成千上万哈)或者你要争取毫秒级操作,那么理解这个概念就很关键了 。而且你猜怎么着,数据库要同时处理这两种情景!我不会占用你太长时间,只要你能明白这一点就够了 。这个概念在下文会帮助我们理解什么是基于成本的优化 。
概念
时间复杂度用来检验某个算法处理一定量的数据要花多长时间 。为了描述这个复杂度,计算机科学家使用数学上的『简明解释算法中的大O符号』 。这个表示法用一个函数来描述算法处理给定的数据需要多少次运算 。
比如,当我说『这个算法是适用 O(某函数())』,我的意思是对于某些数据,这个算法需要 某函数(数据量) 次运算来完成 。
重要的不是数据量,而是当数据量增加时运算如何增加 。时间复杂度不会给出确切的运算次数,但是给出的是一种理念 。
如果再有人问你数据库的原理,把这篇文章给他

文章插图
 
图中可以看到不同类型的复杂度的演变过程,我用了对数尺来建这个图 。具体点儿说,数据量以很快的速度从1条增长到10亿条 。我们可得到如下结论:
  • 绿:O(1)或者叫常数阶复杂度,保持为常数(要不人家就不会叫常数阶复杂度了) 。
  • 红:O(log(n))对数阶复杂度,即使在十亿级数据量时也很低 。
  • 粉:最糟糕的复杂度是 O(n^2),平方阶复杂度,运算数快速膨胀 。
  • 黑和蓝:另外两种复杂度(的运算数也是)快速增长 。
例子
数据量低时,O(1) 和 O(n^2)的区别可以忽略不计 。比如,你有个算法要处理2000条元素 。