【连载】关系型数据库是如何工作的?(6) - Hash表

最后我们介绍的重要数据结构就是Hash表。当你需要快速查找的时候非常有用,而且理解Hash表会有助于我们以后理解常用数据库Join方式之一Hash join。这种数据结构常被数据库用作存储内部数据结构:表锁或缓存池(后续章节会介绍)。

Hash表能够通过元素Key快速找到元素的,为了构建一张Hash表,你需要定义:

  • 一个元素的Key;
  • 一个关于Key的Hash函数,Key的hash值就代表元素所在的位置(我们通常称为Hash桶);
  • 一个关于Key的比较函数,一旦你找到了正确的桶,你就可以通过比较函数找到正确的元素。

一个简单的例子

让我们看一个虚拟的例子:

上图中的Hash表实际有10个桶,Hash函数就是取10的余数,也就是每个Key的个位数字:

  • 如果个位数是0,则元素在0号桶;
  • 如果个位数是1,则元素在1号桶;
  • 如果个位数是2,则元素在2号桶;

比较函数就是比较两个整数是否相同的函数。如果我们想要找到78:

  • Hash表计算的78的哈希值是8;
  • 找到8号桶,第一个元素就是78;
  • 返回78;
  • 整个搜索花费2个操作:1-计算Hash值;2-找到桶中的元素;

如果我们想要找到59:

  • Hash表计算的59的哈希值是9;
  • 找到9号桶,第一个元素是99,99!=59,因此这不是我要找的元素;
  • 用相同的逻辑找到9,79,…,最后一个29;
  • 元素59并不存在;
  • 真个搜索花费7个操作。

好Hash函数的标准

标准依赖于你要查找的值,不同类型的值花费是不同的。

如果将之前例子中的Hash函数换为取1 000 000的余数(也就是最后6位数),第二个例子耗费的操作数就会降为1,因为在000059号桶中没有元素。实际上,真正的难点就是找到一个能够尽可能降低每个桶中元素数量的Hash函数。(译者注:我们一般称之为降低Hash冲突

在上述两个例子中,找到一个好的Hash函数很容易。但是当Key是下列类型时,找到一个好Hash函数很困难:

  • 1个字符串,比如一个人的名字;
  • 2个字符串,比如一个人的姓+名字;
  • 2个字符串和一个日期,比如一个人的姓+名字+出生日期。

只要拥有一个足够好的Hash函数,搜索的时间复杂度就是O(1)。

数组和Hash表的比较

什么情况下需要使用数组呢?这是一个好问题!

  • 基于Hash的数据库表,可以在内存中只加载一般的桶,其他桶可以留在磁盘上;
  • 数组必须占用一个连续的内存空间,如果一个基于二维数组的数据库表很大,那么要在内存中找到足够的连续空间很困难;
  • 基于Hash的数据库表,你可以选择任意的Key,比如可以选择Key为国家+名字。

关于更多的信息,可以参考我写的另外一篇文章Java HashMap。但理解这篇文章并不要求你理解Java。

下一章我们来开始介绍数据库的整体视图。

时间: 2024-09-29 01:43:21

【连载】关系型数据库是如何工作的?(6) - Hash表的相关文章

【连载】关系型数据库是如何工作的?(9) - 查询管理器

查询管理器 查询管理是一个数据库强大与否的一个判断指标.通过查询管理,可以把一个糟糕的查询语句转换为一段快速执行的代码,代码执行后返回结果给客户端管理器.整个过程分为多步: 查询首先被解析并检查其有效性: 重写查询并删除不必要的操作,另外做一些预优化: 为了提升性能进行必要的优化,最终转换为一个执行计划: 编译执行计划: 最后运行执行计划. 在读了这一章节之后,如果对查询优化想更深入的理解,我推荐阅读以下资料: 1979年发表的一篇最早的关于基于成本优化的论文:Access Path Selec

【连载】关系型数据库是如何工作的?(4) - 数组、二叉搜索树

在我们理解了隐藏在时间复杂度和排序后面的思想之后,我必须再谈谈3种数据结构了.它们极其重要,因为它们是现代数据库的基石.我也会顺便介绍下索引的概念. 数组 二维数组是最简单的数据结构,一张数据库表就可以看做一个二维数组,例如: 二维数组就是一个既有行又有列的表: 一行就表示一个主题(记录) 一列就是描述主题(记录)的一个特性 每一列存储同一个类型的数据(integer, string, date -) 虽然表能很好的存储并展示数据,但是当你需要搜索数据时,它的表现就很糟糕了. 例如,如果你要找到

【连载】关系型数据库是如何工作的?(5) - B+Tree索引

虽然上一章节介绍的二叉搜索树在查询指定值时表现很好,但是当查询两个值之间的多个节点时,就会遇到很大的问题.因为需要遍历整个树的节点,并检查每个节点是否在指定的区间内.而且遍历整颗树是随机磁盘IO(译者注:随机IO会导致频繁的磁头换道,所以相比顺序IO来说非常耗时),所以我们需要找到一种更有效做范围查询的方法.为了解决这个难题,现代数据库修正了之前介绍的二叉搜索树,我们称修正后的数据结构为B+Tree: 只有叶子节点(树最底层的节点,图中橘黄色的节点)存储信息,即:行在表中精确的位置,也就是row

【连载】关系型数据库是如何工作的?(7) - 数据库架构视图

现在我们可以看看数据库内部都有什么组件.一个数据库就是容易访问和修改的信息集合,实际上,一组简单的文件就可以做到.最简单的数据库SQLite就是由一组简单文件组成的,并且是一组精心设计的一组文件,它允许你: 通过事务保证数据的安全性和一致性: 即时海量数据也能保证快速处理数据. 通常,一个数据的组件视图如下: 在写下这部分内容之前,我阅读了很多书籍和论文,每一个都有其特有的方式来描述数据库.因此就不要纠结我怎么组织数据库,或者我怎么命名这些组件,因为我已经为此考虑良久来适合这篇文章.不同的组件并

【连载】关系型数据库是如何工作的?(11) - 查询管理器之重写

在重写这一步,我们拿到了查询SQL的内部表示,重写的目的是: 预优化SQL 避免不必要的操作 帮助优化器找到尽可能好的解决方案 重写器会在查询上匹配一系列规则,如果匹配一个规则就应用它重写查询,以下是部分可选的规则: 视图合并:如果你在查询中用了视图,那么视图就会被转换为一段代码: 优化子查询:由于一个子查询非常难以优化,因此重写器会修改子查询并删除子查询. 例如: SELECT PERSON.* FROM PERSON WHERE PERSON.person_key IN (SELECT MA

关系型数据库工作原理-事务管理(二)(翻译自Coding-Geek文章)

本文翻译自Coding-Geek文章:< How does a relational database work>. 原文链接:http://coding-geek.com/how-databases-work/#Buffer-Replacement_strategies 紧接上一篇文章,本文翻译了如下章节: 一. Log manager(日志管理) 通过前面的章节,我们已经知道,为了提升性能,数据库会将数据缓存在内存中.但是,如果在事务提交过程中,数据库服务器崩溃了.缓存在内存的数据就会丢失

关系型和非关系型数据库的区别--转载

关系型数据库和非关系型数据库 关系数据库和非关系数据库的区别是,关系数据库只有“表”这一种数据结构:而非关系数据库系统还有其他数据结构,对这些数据结构还有其他操作. 随着网络的不断发展,单纯关系数据库面临挑战. 关系与非关系型数据库的特点 1.关系型数据库 关系型数据库,是指采用了关系模型来组织数据的数据库. 简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织. 关系模型中常用的概念: 关系:可以理解为一张二维表,每个关系都具有一个关系名,就

深入理解关系型数据库(一)

前言:是否写了很多年的SQL查询,仍然不知道这个大盒子里怎么运作的? 如果你感兴趣,不妨读读本文. 每当说到关系型数据库时,我总感觉少点什么.各式各样的数据库被到处使用,从轻量的SQLite到强大的Teradata.但是,几乎没有一篇文章来解释这些关系型数据库到底是怎样工作的.你使用谷歌搜索“关系型数据库的运行原理”,基本上搜不到什么结果.现在,如果你有接触到比较流行的技术(Big Data, NoSQL或者JavaScript),你却可以找到一些比较深入的介绍它们原理的文章. 难道关系型的数据

关系型数据库和非关系型数据库

目前的市面上的关系型数据有:Oracle.DB2.Microsoft SQL Server.Microsoft Access.MySQL等. 非关系型数据库有:NOSQL,Cloudant 非关系型数据库主流的还是NOSQL,  那么 NOSQL和关系型数据库的区别是: 优:1.成本:nosql数据库简单易部署,基本都是开源软件,不需要像使用oracle那样花费大量成本购买使用,相比关系型数据库价格便宜. 2.查询速度:nosql数据库将数据存储于缓存之中,关系型数据库将数据存储在硬盘中,自然查