51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1976|回复: 1
打印 上一主题 下一主题

[转自网络]关系型数据库工作原理-时间复杂度(翻译自Coding-Geek文章)

[复制链接]
  • TA的每日心情
    擦汗
    前天 09:02
  • 签到天数: 1042 天

    连续签到: 4 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2016-4-21 14:05:12 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

    本文翻译自Coding-Geek文章:《 How does a relational database work》。

    原文链接:http://coding-geek.com/how-databases-work/#Buffer-Replacement_strategies

    本文翻译了如下章节:


    一、 前言

    谈到关系型数据库,我想不到有什么东西能缺少它,可以说关系型数据已经无处不在。存在各种不同的关系型数据库:从轻量有用的SQLite到功能强悍的数据仓库。
    但是,这只是一篇介绍关系型数据库工作原理的简短文章。你可以google“关系型数据库工作原理”,介绍数据库工作原理的文章少之又少。并且,即使有,这些文章有也很简短;原理也没有讲透。如果你搜索当前最流行的技术(Big Data、NoSQL和JavaScript),你能找到很多深入讲解它的原理的文章。
    是关系型数据库太老,技术太陈旧了吗? 除了大学课堂和研究论文外,没有人感兴趣,去说一下它的原理。


    作为一个程序员,我讨厌使用我不理解的东西。并且,如果一种数据库已经使用了超过40年,那一定是有原因的。这些年,我花了成百上千个小时去弄懂我每天都在使用的数据库下面的黑盒。关系型数据库非常有趣,因为它是基于一些非常有用的,可推而广之的理念。如果你对数据库非常感兴趣,但是没有时间深入去研究整个数据库领域。那么这篇文章将非常适合你。

    本文的标题已经很明确,这不是一篇介绍如何使用数据库的文章。因此,你应该已经知道如何写简单的连表查询和基础的CRUD数据库操作SQL语句。否则,你可能无法理解本文。这是你需要提前掌握的基础知识,其它知识本文都会逐一讲解。

    本文是一篇篇幅长,技术性很强的文章;包含很多算法和数据结构。需要花费你较多的时间去阅读。一些概念很难理解,你可以跳过它们去了解文章的大意。
    为了方便你掌握,文章分为三部分:

    • 整体介绍数据库包含哪些组件。
    • 查询优化概述。
    • 事务和缓存处理介绍。
    二、Back To Basic-回到基本概念上

    很久以前(银河系诞生之前…哈哈), 开发者必须很明确的知道所编写代码需要使用的CPU操作指令数量。他们对代码中用到的算法和数据结构明察秋毫,因为他们不能浪费一丁点CPU和内存资源。计算机太慢了,资源很宝贵。

    本章,我将唤起你对一些基本概念的学校记忆,理解这些概念对理解数据库不必可少。我也会介绍什么是数据库索引。

    (一)O(1) VS O(n^2)

    现今,很多程序员不关柱时间复杂度,而且… 他们往往还是对的!
    但是,当你处理大数据的时候(不是仅有几千条数据)或者你在为优化性能到毫秒级奋战的时候。理解时间负杂度的概念就非常关键。想象一下,数据库要同时处理上面两种场景。我不会浪费你太多时间,仅仅介绍一下基本概念。这将帮助我们后面理解 Cost Based Optimization概念。

    (二)The Concept - 基本概念

    时间复杂度被用于衡量一个算法处理指定量的数据所花费的时间。为了描述时间复杂度,计算机科学家使用数学符号大写的O表示。这个符号通常与一个函数结合使用,这个函数描述了一个算法处理指定数量的输入数据需要执行的CPU指令条数。

    例如,当我说“某个算法是O(some_function())”时,意思是对于给定数量的数据,该算法需要执行的指令条数是some_function(数据数量)。
    重要的不是数据的数量或者指令的数量,而是随着数据量的增长,指令数量将以什么样的方式向上增加。时间复杂度不能用于统计一个算法需要执行的精确指令条数,但是是一个用于评估的好方法。


    在这张图中,你能看到不同时间复杂的演化。数据量我按指数级逐渐放大,换句话讲,数据将从1很快增长到10亿。我们看一下不同时间复杂度算法需要执行的指令数量如何变化:
    1. (1)始终保持常量(否则,它也就不叫常量时间复杂度了)。
    2. O(log(n))始终保持在一个低增长率,即使数据量达到10亿级。
    3. 最差的是O(n^2)。操作指令数量随数据量增大,急速膨胀。
    4. 另外两种时间复杂度也增长得很快。

    (三)Examples – 举个例子

    在数据量很小的时候,O(1)和O(n2)的差异可以忽略不计。例如,假设我们的算法要处理2000条数据:
    1. O(1)的算法需要执行1条CPU指令。
    2. O(log(n))的算法需要执行7条指令。
    3. O(n)的算法需要执行2000条指令。
    4. O(n*log(n))的算法需要执行14000条指令。
    5. O(n^2)的算法需要执行4000000条指令。

    O(1)和O(n2)的差异看起来很大, 差了4百万。实际上执行时间最多差2毫秒,相当于眨一下眼睛的时间。确实,现代处理已经能每秒处理几百万条指令。这也是为什么性能优化在很多IT项目里面不是重心。

    但是 听我说,理解这些概念在处理超大数据时仍然非常有用。如果要处理的数据变成了1000000条(对数据库来讲,也不是很大的数据量):

    • O(1)的算法需要执行1条CPU指令。
    • O(log(n))的算法需要执行14条指令。
    • O(n)的算法需要执行1000000条指令。
    • O(n*log(n))的算法需要执行14000000条指令。
    • O(n^2)的算法需要执行1000000000000条指令。

    我无法精确计算,但是我敢说执行一次O(n2)的算法,你可以去喝一杯咖啡了(或者是两杯)。如果在数据量上再加一个0,你就可以去睡一觉了。

    (四) Going Deeper – 更深入一点

    抛出一个观点:

    • 在一个优秀的Hash Table中查询一个元素的时间复杂度是O(1)。
    • 在一个优秀的的二叉平衡树中查询一个元素的时间复杂度是O(log(n))。
    • 在一个数据组查询一个元素的时间复杂度是O(n)。
    • 最好的排序算法的时间复杂度是O(n*log(n))。
    • 差的排序算法的时间复杂度是O(n2)。
      备注:下面我们将看一下这些算法和数据结构。

    一个算法的时间复杂度也分多种场景:

    • 通用场景下的时间复杂度。
    • 最优场景下的时间复杂度。
    • 最差场景下的时间复杂度。

    一个算法的时间复杂度通常就是最差场景下的时间复杂度。

    我仅谈论了算法的时间复杂度,实际上算法的复杂度还包含这些:

    • 算法消耗的内存大小。
    • 算法消耗的磁盘I/O。

    当然,还有比O(n^2)更差的一些时间复杂度:

    • O(n^4):该死,我将会提到有这样复杂度的算法。
    • O(3^n):更糟糕,我们将会在后面文章中看到一个这样的算法(而且,它真的在很多数据库中用到过)。
    • 斐波拉西 N: 你永远也不会计算出结果来,即使很小的数据量。
    • O(n^n):如果你写出了这样一个算法,你该思考一下你是否适合呆在IT领域。

    备注:我并没有给符号O下一个准确的定义,我只是介绍了他的思想。如果你想了解它真正它的真正含义,可以上维基百科。


    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏1
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-9 04:44 , Processed in 0.063549 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表