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

  • O(n) 算法会消耗 2000 次运算
  • O(n*log(n)) 算法会消耗 14,000 次运算
  • O(n^2) 算法会消耗 4,000,000 次运算
  • O(1) 和 O(n^2) 的区别似乎很大(4百万),但你最多损失 2 毫秒,只是一眨眼的功夫 。确实,当今处理器每秒可处理上亿次的运算 。这就是为什么性能和优化在很多IT项目中不是问题 。
    我说过,面临海量数据的时候,了解这个概念依然很重要 。如果这一次算法需要处理 1,000,000 条元素(这对数据库来说也不算大) 。
    • O(1) 算法会消耗 1 次运算
    • O(log(n)) 算法会消耗 14 次运算
    • O(n) 算法会消耗 1,000,000 次运算
    • O(n*log(n)) 算法会消耗 14,000,000 次运算
    • O(n^2) 算法会消耗 1,000,000,000,000 次运算
    我没有具体算过,但我要说,用O(n^2) 算法的话你有时间喝杯咖啡(甚至再续一杯!) 。如果在数据量后面加个0,那你就可以去睡大觉了 。
    继续深入
    为了让你能明白
    • 搜索一个好的哈希表会得到 O(1) 复杂度搜索一个均衡的树会得到 O(log(n)) 复杂度搜索一个阵列会得到 O(n) 复杂度最好的排序算法具有 O(n*log(n)) 复杂度糟糕的排序算法具有 O(n^2) 复杂度
    注:在接下来的部分,我们将会研究这些算法和数据结构 。
    有多种类型的时间复杂度
    • 一般情况场景
    • 最佳情况场景
    • 最差情况场景
    时间复杂度经常处于最差情况场景 。
    这里我只探讨时间复杂度,但复杂度还包括:
    • 算法的内存消耗
    • 算法的磁盘 I/O 消耗
    当然还有比 n^2 更糟糕的复杂度,比如:
    • n^4:差劲!我将要提到的一些算法具备这种复杂度 。
    • 3^n:更差劲!本文中间部分研究的一些算法中有一个具备这种复杂度(而且在很多数据库中还真的使用了) 。
    • 阶乘 n:你永远得不到结果,即便在少量数据的情况下 。
    • n^n:如果你发展到这种复杂度了,那你应该问问自己IT是不是你的菜 。
    注:我并没有给出『大O表示法』的真正定义,只是利用这个概念 。可以看看维基百科上的这篇文章 。
    合并排序当你要对一个集合排序时你怎么做?什么?调用 sort() 函数……好吧,算你对了……但是对于数据库,你需要理解这个 sort() 函数的工作原理 。
    优秀的排序算法有好几个,我侧重于最重要的一种:合并排序 。你现在可能还不了解数据排序有什么用,但看完查询优化部分后你就会知道了 。再者,合并排序有助于我们以后理解数据库常见的联接操作,即合并联接。
    合并
    与很多有用的算法类似,合并排序基于这样一个技巧:将 2 个大小为 N/2 的已排序序列合并为一个 N 元素已排序序列仅需要 N 次操作 。这个方法叫做合并 。
    我们用个简单的例子来看看这是什么意思:
    如果再有人问你数据库的原理,把这篇文章给他

    文章插图
     
    通过此图你可以看到,在 2 个 4元素序列里你只需要迭代一次,就能构建最终的8元素已排序序列,因为两个4元素序列已经排好序了:
    • 1) 在两个序列中,比较当前元素(当前=头一次出现的第一个)
    • 2) 然后取出最小的元素放进8元素序列中
    • 3) 找到(两个)序列的下一个元素,(比较后)取出最小的
    • 重复1、2、3步骤,直到其中一个序列中的最后一个元素
    • 然后取出另一个序列剩余的元素放入8元素序列中 。
    这个方法之所以有效,是因为两个4元素序列都已经排好序,你不需要再『回到』序列中查找比较 。【合并排序详细原理,其中一个动图(原图较长,我做了删减)清晰的演示了上述合并排序的过程,而原文的叙述似乎没有这么清晰,不动戳大 。】
    如果再有人问你数据库的原理,把这篇文章给他

    文章插图
     
    既然我们明白了这个技巧,下面就是我的合并排序伪代码 。
    C
    如果再有人问你数据库的原理,把这篇文章给他

    文章插图
     
    合并排序是把问题拆分为小问题,通过解决小问题来解决最初的问题(注:这种算法叫分治法,即『分而治之、各个击破』) 。如果你不懂,不用担心,我第一次接触时也不懂 。如果能帮助你理解的话,我认为这个算法是个两步算法:
    • 拆分阶段,将序列分为更小的序列
    • 排序阶段,把小的序列合在一起(使用合并算法)来构成更大的序列
    拆分阶段
    如果再有人问你数据库的原理,把这篇文章给他


    推荐阅读