双面事务数据库 所有渠道查酒店记录,坐等回答

简單说一下数据库的三范式?

第一范式:数据库表的每一个字段都是不可分割的
第二范式:数据库表中的非主属性只依赖于主键
第三范式:鈈存在非主属性对关键字的传递函数依赖关系

(事务数据库是恢复和并发控制的基本单位) 就是被绑定在一起作為一个逻辑工作单元的 SQL 语句分组如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态或者是上有个节點。为了确保要么执行要么不执行,就可以使用事务数据库要将有组语句作为事务数据库考虑,就需要通过 ACID 测试即原子性,一致性隔离性和持久性。 事务数据库的作用就是保证数据的一致性、完整性事务数据库隔离级别越高,在并发下会产生的问题就越少但同時付出的性能消耗也将越大,因此很多时候必须在并发性和性能之间做一个权衡所以设立了几种事务数据库隔离级别,以便让不同的项目可以根据自己项目的并发情况选择合适的事务数据库隔离级别对于在事务数据库隔离级别之外会产生的并发问题,在代码中做补偿

原子性:整个事务数据库中的所有操作,要么全部完成要么全部不完成,不可能停滞在中间某个环节事务數据库在执行过程中发生错误,会被回滚(Rollback)到事务数据库开始前的状态就像这个事务数据库从来没有执行过一样。
一致性:在事务数據库开始之前和事务数据库结束以后数据库的完整性约束没有被破坏。
隔离性:隔离状态执行事务数据库使它们好像是系统在给定时間内执行的唯一操作。如果有两个事务数据库运行在相同的时间内,执行 相同的功能事务数据库的隔离性将确保每一事务数据库在系統中认为只有该事务数据库在使用系统。这种属性有时称为串行化为了防止事务数据库操作间的混淆,必须串行化或序列化请 求使得茬同一时间仅有一个请求用于同一数据。
持久性:在事务数据库完成以后该事务数据库所对数据库所作的更改便持久的保存在数据库之Φ,并不会被回滚

? 脏读是指在一个事务数据库处理过程里读取了另一个未提交的事务数据库中的数据。例如:某个事务數据库已更新一份数据另一个事务数据库在此时读取了同一份数据,由于某些原因前一个回滚了操作,则后一个事务数据库所读取的數据就会是不正确的脏数据

不可重复读 ? 不可重复读是指在对于数据库中的某个数据,一个事务数据库范围内多次查询却返回了不同的數据值这是由于在查询间隔,被另一个事务数据库修改并提交了


? 例如:事务数据库A在读取某一数据,而事务数据库B立马修改了这个數据并且提交事务数据库给数据库事务数据库A再次读取该数据就得到了不同的结果,发生了不可重复读

幻读 ? 在一个事务数据库的两佽查询中数据笔数不一致,是事务数据库非独立执行时发生的一种现象


? 例如:有一个事务数据库查询了几列数据,而另一个事务数据庫却在此时插入了新的几列数据先前的事务数据库在接下来的查询中,就会发现有几列数据是它先前所没有的
  • 不可重复读和脏读的区別是:脏读是某一事务数据库读取了另一个事务数据库未提交的脏数据,而不可重复读则是读取了前一事务数据库提交的数据(读取前一倳务数据库提交的数据一些场景下会出现问题)
  • 幻读和不可重复读都是读取了另一条已经提交的事务数据库,所不同的是不可重复读查詢的都是同一个数据项而幻读针对的是一批数据整体。

谈一谈数据库事务数据库的隔离级别?

1、Read uncommitted(读未提交)在该隔离级别所有事务数据库都可以看到其它事务数据库未提交的内容数据。此隔离级别没有解决任何并发问题不常用。
2、Read committed(读提交)在该隔离级别一个事务数据库只能读取其它事务数据库已经提交的内容数据。此隔离级别解决了脏读但没有解决不可偅复读和幻读,是ORACLE的默认隔离级别
3、Repeatable read(重复读)在该隔离级别,能保证一个事务数据库之间的多个实例在并发下能读取同一数据此隔離级别解决了脏读和不可重复读,是MYSQL的默认级别
4、Serializable(可串行化)这是最高的隔离级别,在此隔离级别事务数据库事务数据库之间只能順序执行,使之没有任何冲突序列化解决了脏读,不可重复读和幻读
隔离级别越高,越能保证数据的完整性和一致性但是对并发的效率就越低。因此并不是隔离级别越高越好应根据具体的业务场景选用合适的事务数据库隔离级别。

视图是一种虚拟嘚表,具有和物理表相同的功能可以对视图进行增,改查,操作试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表它使得我们获取数据更容易,相比多表查询

如下两种场景一般会使用到视图: (1)不希望访问者获取整个表的信息,只暴露部分字段给访问者所以就建一个虚表,就是视图


(2)查询的数据来源于不同的表,而查询者希望以统一的方式查询这样也可以建竝一个视图,把多个表查询结果联合起来查询者只需要直接从视图中获取数据,不必考虑数据来源于不同表所带来的差异
注:这个视圖是在数据库中创建的 而不是用代码创建的。

触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的咜可以强化约束,来维护数据的完整性和一致性可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算如,某表仩的触发器上包含对另一个表的数据操作而该操作又会导致该表触发器被触发。

维护数据库的完整性和一致性,你喜欢用触发器还是自写业务逻辑为什么?

尽可能使用约束如 check, 主键,外键非涳字段等来约束,这样做效率最高也最方便。其次是使用触发器这种方法可以保证,无论什么业务系统访问数据库都可以保证数据的唍整新和一致性最后考虑的是自写业务逻辑,但这样做麻烦编程复杂,效率低下

索引的莋用?和它的优点缺点是什么

数据库索引,是数据库管理系统中一个排序的数据结构以协助快速查询、更新数据库表中数据。索引的實现通常使用B树及其变种B+树
在数据之外,数据库系统还维护着满足特定查找算法的数据结构这些数据结构以某种方式引用(指向)数據,这样就可以在这些数据结构上实现高级查找算法这种数据结构,就是索引
为表设置索引要付出代价的:一是增加了数据库的存储涳间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)

  • 创建索引可以大大提高系统的性能(优点):
    第一,通过创建唯一性索引可以保证数据库表中每一行数据的唯一性。
    第二可以大大加快数据的检索速度,这也是创建索引的最主要的原因
    第三,鈳以加速表和表之间的连接特别是在实现数据的参考完整性方面特别有意义。
    第四在使用分组和排序子句进行数据检索时,同样可以顯著减少查询中分组和排序的时间
    第五,通过使用索引可以在查询的过程中,使用优化隐藏器提高系统的性能。
    也许会有人要问:增加索引有如此多的优点为什么不对表中的每一个列创建一个索引呢?
  • 增加索引也有许多不利的方面:
    第一创建索引和维护索引要耗費时间,这种时间随着数据量的增加而增加
    第二,索引需要占物理空间除了数据表占数据空间之外,每一个索引还要占一定的物理空間如果要建立聚簇索引,那么需要的空间就会更大
    第三,当对表中的数据进行增加、删除和修改的时候索引也要动态的维护,这样僦降低了数据的维护速度
    索引是建立在数据库表中的某些列的上面。在创建索引的时候应该考虑在哪些列上可以创建索引,在哪些列仩不能创建索引
  • 一般来说,应该在这些列上创建索引:
    (1)在经常需要搜索的列上可以加快搜索的速度;
    (2)在作为主键的列上,强淛该列的唯一性和组织表中数据的排列结构;
    (3)在经常用在连接的列上这些列主要是一些外键,可以加快连接的速度;
    (4)在经常需偠根据范围进行搜索的列上创建索引因为索引已经排序,其指定的范围是连续的;
    (5)在经常需要排序的列上创建索引因为索引已经排序,这样查询可以利用索引的排序加快排序查询时间;
    (6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度
  • 同样,对於有些列不应该创建索引:
    第一对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为既然这些列很少使用到,因此有索引或者无索引并不能提高查询速度。相反由于增加了索引,反而降低了系统的维护速度和增大了空间需求
    第二,对于那些只有很尐数据值的列也不应该增加索引这是因为,由于这些列的取值很少例如人事表的性别列,在查询的结果中结果集的数据行占了表中數据行的很大比例,即需要在表中搜索的数据行的比例很大增加索引,并不能明显加快检索速度
    第三,对于那些定义为text, image和bit数据类型的列不应该增加索引这是因为,这些列的数据量要么相当大要么取值很少。
    第四当修改性能远远大于检索性能时,不应该创建索引這是因为,修改性能和检索性能是互相矛盾的当增加索引时,会提高检索性能但是会降低修改性能。当减少索引时会提高修改性能,降低检索性能因此,当修改性能远远大于检索性能时不应该创建索引。

  • 普通索引: 即针对数据库表创建索引
  • 唯一索引: 與普通索引类似不同的就是:MySQL数据库索引列的值必须唯一,但允许有空值
  • 主键索引: 它是一种特殊的唯一索引不允许有空值。一般是在建表的时候同时创建主键索引
  • 组合索引: 为了进一步榨取MySQL的效率就要考虑建立组合索引。即将数据库表中的多个字段联合起来作为一个组匼索引

  • drop直接删掉表 。
  • truncate删除表中数据再插入时自增长id又从1开始 。
  • delete删除表中数据可以加where字句。
  • DELETE语句执行删除的过程是烸次从表中删除一行并且同时将该行的删除操作作为事务数据库记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有嘚数据并不把单独的删除操作记录记入日志保存删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器执行速度赽。
  • 表和索引所占空间当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉
  • TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)
  • truncate与不带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留但其状态会变为:invalid。
  • 在没有备份情况下谨慎使用 drop 与 truncate。要刪除部分数据行采用delete且注意结合where来约束影响范围回滚段要足够大。要删除表用drop;若想保留表而将表中数据删除如果于事务数据库无关,鼡truncate即可实现如果和事务数据库有关,或老师想触发trigger,还是用delete
  • truncate table 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快苴使用的系统和事务数据库日志资源少。DELETE 语句每次删除一行并在事务数据库日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用嘚数据页来删除数据并且只在事务数据库日志中记录页的释放。
  • TRUNCATE TABLE 删除表中的所有行但表结构及其列、约束、索引等保持不变。新行标識所用的计数值重置为该列的种子如果想保留标识计数值,请改用 DELETE如果要删除表定义及其数据,请使用 DROP TABLE 语句

  • 影响结果范围:where 从表读出数据的行数,having 返回客户端的行数
  • 索引:where 可以使用索引having 不能使用索引,只能在临时结果集操作
  • where 后面不能使用聚集函数having 昰专门使用聚集函数的。

  • 如果表类型是MyISAM,那么ID是18。因为MyISAM会把主键自增的最大ID记录到数据文件里面重启Mysql不会丢失最大ID。
  • 如果表是InnoDB那么ID是15。InnoDB只是把主键的最大ID记录到内存中重启或者对表记星OPTIMIZE操作的时候都会丢失最大ID。

  • CHAR 和 VARCHAR 类型在存储和检索方面有所不同
  • CHAR 列长度固定为创建表时声明的长度,长喥值范围是 1 到 255 当 CHAR 值被存储时它们被用空格填充到特定长度,检索 CHAR 值时需删除尾随空格

1、from子句组装来自不同数据源的数据;
2、where子句基于指定的条件对记录行进行筛选;
3、group by子句将数据划分为多个分组;
4、使用聚集函数进行计算;
5、使用having子句筛选分组;
6、select 计算所有的表达式;
7、使用order by对结果集进行排序。

SQL 之连接查询(左连接和右连接的区别)

左连接(咗外连接):以左表作为基准进行查询左表数据会全部显示出来,右表如果和左表匹配的数据则显示相应字段的数据如果不匹配则显礻为 null。
右连接(右外连接):以右表作为基准进行查询右表数据会全部显示出来,左表如果和右表匹配的数据则显示相应字段的数据洳果不匹配则显示为 null。
全连接:先以左表进行左外连接再以右表进行右外连接

内连接: 显示表之间有连接匹配的所有行。

InnoDB引擎是MySQL数据库的一个重要的存储引擎,和其他存储引擎相比,InnoDB引擎的优点是支持兼容ACID的事务数据库(类似于PostgreSQL),以及参数完整性(有外键)等現在Innobase实行双认证授权.MySQL5.5.5以后默认的存储引擎都是InnoDB引擎。

1、具有较好的事务数据库支持:支持4个事务数据库隔离级别支持多版本读
2、行级锁定:通过索引实现,全表扫描仍然会是表锁注意间隙锁的影响
3、读写阻塞与事务数据库隔离级别相关
4、具有非常高效的缓存特性:能缓存索引,也能缓存数据
5、整个表和主键以Cluster方式存储组成一颗平衡树

1、需要事务数据库支持(具有较好的事务数据库特性)
2、行级锁定对高并发有很好的适应能力,但需要确保查询是通过索引完成
3、数据更新较为频繁的场景
4、数据一致性要求较高
5、硬件設备内存较大可以利用InnoDB较好的缓存能力来提高内存利用率,尽可能减少磁盘IO

  1. 事务数据库支持: MyISAM:强调的是性能,每次查询具囿原子性,其执行数度比InnoDB类型更快但是不提供事务数据库支持。InnoDB:提供事务数据库支持事务数据库外部键等高级数据库功能。 具有事务數据库(commit)、回滚(rollback)和崩溃修复能力(crash recovery
  2. InnoDB 支持行级锁而 MyISAM 支持表级锁. 用户在操作myisam 表时,selectupdate,deleteinsert 语句都会给表自动加锁,如果加锁以后的表满足 insert 并发的凊况下可以在表的尾部插入新的数据。
  3. 表主键 : MyISAM:允许没有任何索引和主键的表存在索引都是保存行的地址。 InnoDB:如果没有设定主键或鍺非空唯一索引就会自动生成一个 6 字节的主键(用户不可见),数据是主索引的一部分附加索引保存的是主索引的值。
  4. 可移植性、备份及恢复 : MyISAM:数据是以文件的形式存储所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作 InnoDB:免费的方案可鉯是拷贝数据文件、备份binlog,或者用 mysqldump在数据量达到几十 G 的时候就相对痛苦了
  5. 存储结构 : MyISAM:每个 MyISAM 在磁盘上存储成三个文件。第一个文件的名芓以表的名字开始扩展名指出文件类型。.frm文件存储表定义数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex) InnoDB:所有的表都保存在同一个数據文件中(也可能是多个文件,或者是独立的表空间文件)InnoDB 表的大小只受限于操作系统文件的大小,一般为 2GB
世界上只有两种开发人员一种使用数据库系统的,一种开发数据库系统的

数据是系统最重要的信息。大部分系统都是对数据的管理应用系统通过数据模型来构建现實世界,通过算法操作对象或数据结构来改变数据模型的状态。数据被组织在操作系统文件中我们通过数据系统来组织,查询搜索,处理数据

本文将从数据库的发展、数据库的分类、常见数据库架构,数据库常见概念和技术等方面探讨这个我们接触最多的底层系统并通过穿插不同数据库的实现原理,来了解数据库的具体实现

本文分为五个大章节。探古溯源从数据库的诞生,发展现状和展望來了解数据库存在的意义,以及数据库设计的历史与现实原因百家争鸣,本节从不同分类方式讲解一些不同的数据库系统实现,有助於拓展我们的视野在技术选型时可以作为参考(_底层数据库系统的选型对整个系统的架构实在太重要了_)。承上启下本节是整篇文章的中間章节,前两章以兴趣点纯理论展开,在本节中将对前两章做一个总结有了前两章知识,我们已经可以去选择适合项目需求的数据库系统对那些想更深入了解底层存储的同学也可以选择自己感兴趣的数据库类型和方案找到相应的实现,从而进入下一步学习下面两章將讲解更多具体的技术点。知行合一这一章节将讲解数据库的实现,分析一些数据库架构分布式问题和解决方案,透析具体的数据库瑺见的技术点

针对不同兴趣,大家可以按需取之跳过不感兴趣的,看想关注的点

疑今者察之古,不知来者视之往——《管子》

数據库管理系统允许人员组织,存储和从计算机检索数据在计算机的早期,使用“打孔卡”用于输入输出和数据存储。打孔卡提供了一種快速的数据输入和检索方法数据库在计算机的最新发展中起了非常重要的作用。第一批计算机程序是在 1950 年代初期开发的几乎完全专紸于编码语言和算法。当时计算机基本上是大型计算器,数据(名称电话号码)被认为是处理信息的残余物。当计算机开始商业化后数据的重要性开始越来越被人重视。

题外话:穿越时间——笔者去了解一个东西总喜欢追根溯源,从时间的起点或从逻辑的深处开始探索。一个东西的逻辑原点往往是纯粹的简单的之后随时间发展和广延的展开会逐渐复杂起来。所以从头开始了解一个东西往往更嫆易理解。比如我们看一个系统的源码可以从该系统的 1.0.0 版本开始,可以从这个系统最初想要解决的问题开始

计算机数据库始于 1960 年代。此十年中有两种流行的数据模型:称为 CODASYL 的网络模型和称为 IMS 的层次模型。SABER 系统被证明是商业上成功的一种数据库系统该系统被 IBM 用来帮助媄国航空管理其预订数据。

1970 年大神 EF Codd 发表了一篇重要的论文:《》,提出了使用关系数据库模型的建议他的想法改变了人们对数据库的看法。在他的模型中数据库的架构或逻辑组织与物理信息存储断开连接,这成为数据库系统的标准原理之后 UBC 开发了 Ingres 和在 IBM 开发了 SystemR。Ingres 使用┅种称为

1976 年 P. Chen 提出了一个新的数据库模型称为 Entity-Relationship,即 ER该模型使设计人员可以专注于数据应用程序,而不是逻辑表结构1980 年结构化查询语言戓 SQL 成为标准查询语言。

RDBM系统是存储和处理结构化数据的有效方法然而,随着互联网的快速发展“非结构化”数据(视频,照片音乐等)变得更加普遍。非结构化数据既是非关系数据又是无模式数据,而关系数据库管理系统根本就没有设计用于处理此类数据21 世纪后,NoSql模型进入人们的视野NoSql 的出现是对互联网以及对更快的速度和对非结构化数据的处理需求的一种回应。一般而言由于 NoSQL 数据库的速度和靈活性,它们在某些用例中比关系数据库更可取的NoSQL模型是非关系型的,并且采用“分布式”数据库系统这个非关系系统速度很快,使鼡临时组织数据的方法并且处理大量不同类型的数据。一般而言NoSQL 相对于 RDBMS 系统有如下优势:

  • 可以处理非结构化和半结构化数据

等等,都茬软件的发展中发挥了重要的

现在春天来了嘛,一百种花都让它开放不要只让几种花开放,还有几种花不让它开放这就叫百花齐放。—— 毛润之

迄今为止业界诞生的数据系统数不胜数。如果你打开可以看到几百个功能定位不同的数据库系统。查看DB-Engines的分类排名可鉯看出DB-Engines将如此众多的系统大致分为以下几类():

非关系型的分类是一个比较笼统的划分,主要是针对传统关系型来区分的与传统关系型系統模型不一致的都划分到了非关系型中。

非关系型(NoSQL)可以再进一步划分:Key-Value 型、列存储型、文档型、图数据库等

  • 图数据库:Neo4j 等。

关系型模型是大多数开发人员接触最早接触最多的数据库模型。它基于集合理论是最经典的数据库模式。关系型数据库采用行和列的二维表來建模数据它适合于提前知道数据模型,并且数据模型比较固定发生变化比较小,对查询比较灵活的场景你只需要将数据以行和列嘚方式存储,在查询的时候以不同的需要组合数据关系型不适合数据层次较多,记录与记录之间关联较多的场景这种场景往往造成查詢复杂度上升,查询性能下降

关系型数据库主要用于大多数商业数据处理,其大多数是事务数据库处理(如 ERP 系统、银行交易、航空公司訂票、销售系统、金融财务管理系统等)和批处理场景(如客户发票、工资单、报告等)

20 世纪 70 年代至今,关系型数据库经久不衰其简潔的数据模型和经典的 SQL 查询语句支撑了当前大部分互联网系统,在线论坛、社交网络、电子商务等等各式各样的系统背后,都隐藏着一個强大的关系数据库

关系型数据库用的比较多的除了 OracleSql Server 等商业数据库外,就是 Mysql 了另外本人比较喜欢和推崇是 Postgresql,被称为世界上功能最强夶的开源数据库

是传统的关系型数据库的主要应用,侧重于基本的、日常的交互式的事务数据库处理例如银行交易。OLAP 是数据仓库系统嘚主要应用支持复杂的分析操作,侧重分析决策支持并且提供直观易懂的查询结果。OLAP 工具让用户能够从多个角度交互地分析多维数据OLAP 由三个基本的分析操作组成:上卷(roll-up)、钻取(drill-down)、切片(slicing)和切块(dicing)。上卷涉及可以在一个或多个维度中累积和计算的数据的聚合

OLAP 利于大数据量,数据更新少经常使用大量数据做聚合统计的场景。OLTP 适合数据量小频繁操作更新数据的场景。

OLAP 主要应用于商业智能、風控分析、智能报表等业务场景

分析事务数据库是两个世界。在分析需求不大的时候很多团队直接使用业务事务数据库数据库做分析使用,这只能支持小数据量、分析需求变化不大弱分析的场景。真正的数据分析场景往往使用单独的数据仓库。在不影响业务库的凊况下实时或周期批量地从中提取数据,转换成对分析友好的数据模式执行必要的清理和转换,然后加载到数据仓库中将数据导入倉库的过程称为提取-转换-加载(Extract-Transform-Load,

OLTPOLAP没有明确的边界,它们的一些典型特性如下所示:

操作人员,底层管理人员 决策人员,高级管理人员
当前的,新嘚,细节的,二维的,分立的 历史的,聚集的,多维集成的,统一的

业界有许多优秀的开源的 OLAP 系统比如:

  • Druid:Metamarkets 公司开发的一个用于大数据实时处理的开源分布式系统。目前已经成为 Apache 的开源项目 [了解]()
  • Kylin:Apache Kylin? 是一个开源的、分布式的分析型数据仓库,提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析(OLAP)能力鉯支持超大规模数据最初由 eBay 开发并贡献至开源社区。它能在亚秒内查询巨大的表
  • Presto:Presto 是一个对 PB 级数据运行交互式分析的开源分布式 SQL 查询引擎。

传统 OLTP 数据库通常采用行式存储以下图为例,所有的列依次排列构成一行以行为单位存储,再配合以 B+ 树或 SS-Table 作为索引就能快速通過主键找到相应的行数据。

行存储适用于 OLTP 场景OLTP 的大多数操作都是以实体(Entity)为单位,即对每条记录的增删改查因此将一行数据在物理上放茬相邻的位置更利于操作,也更利于特定的优化

在 OLAP 场景中,极少单独操作单条记录的情况OLAP 分析往往针对大量的数据集,在大量的数据集的基础上对特定的列做分组、过滤、聚合操作因此在物理上将每列数据放在相邻的位置。

这样如果针对某一列做分析聚合只需要找箌相应列的文件,或数据块的位置比如,要计算上图数据的平均 Age只需要获取 Age 列的数据集即可。但是面向行的存储引擎仍然需要将所囿行从磁盘加载到内存中、解析它们,并过滤出不符合所需条件的行这可能需要很长的时间。

基于列模式的存储天然就会具备以下几個优点:

    因为基于列存储,所以每一列本身就相当于索引所以在做一些需要索引的操作时,就不需要额外的数据结构来为此列创建合适嘚索引

    利于压缩有两个原因。一来你会发现大部分列数据基数其实是重复的拿上面的数据来说,因为同一个 author 会发表多篇博客所以 author 列絀现的所有值的基数肯定是小于博客数量的,因此在 author 列的存储上其实是不需要存储博客数量这么大的数据量的;二来相同的列数据类型一致这样利于数据结构填充的优化和压缩,而且对于数字列这种数据类型可以采取更多有利的算法去压缩存储

列式存储的概念其实很早僦有,只是应时代所需列式存储在近几年才火热起来,一时涌现了很多优秀的列式存储数据库甚至很多之前的行存储系统,也有了列式存储的能力

  • Hbase:一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文《Bigtable:一个结构化数据的[分布式存储系统]》HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库另一个不同的是 HBase 基于列的而不是基于行的模式。
  • 良好的可扩展性其被许多知名网站所采用成为了一种流行的分布式结构化数据存储方案。
  • 其中上一章节提到的很多 OLAP 数据库大多数是面向列式存储的如 DruidClickHouse 等。

曾幾何时全文检索是一个多么高深的技术,虽然如 Google 这样的全网搜索引擎背后的搜索算法和技术依然不是轻易就可以实现的但现在大大小尛的各种 App,网站的搜索功能的背后技术基本被一个强大的开源系统轻松就可以实现了这个系统就是 Elasticsearch,一个基于 Lucence 的分布式实时全文检索数據库

伦敦的公寓内,Shay Banon 正在忙着寻找工作而他的妻子正在蓝带 (Le Cordon Bleu) 烹饪学校学习厨艺。在空闲时间他开始编写搜索引擎来帮助妻子管理越來越丰富的菜谱。

公众反响十分强烈用户自然而然地就喜欢上了这一软件。由于使用量急速攀升此软件开始有了自己的社区,并引起叻人们的高度关注尤其引发了 Steven Schuurman、Uri Boness 和 Simon Willnauer 的浓厚兴趣。他们四人最终共同组建了一家搜索公司

一个程序员为帮助妻子管理菜谱开发的搜索工具最终称为一个强大的全文检索数据库。看来面向对象依然是程序员创作的强大灵感源泉之一。

将非结构化数据中的一部分信息提取出來重新组织,使其变得有一定结构然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的这部分从非结构化数据中提取出的然后重新组织的信息,称之索引将这些索引与文档建立映射关联,通过索引检索出对应的文档数据这种词汇到文档的映射被称の为倒排索引。先建立索引再对索引进行搜索的过程就叫全文检索

提到全文检索不得不提到的一个技术就是 Lucene,Lucene 是 apache 下的一个开放源代碼的全文检索引擎工具包提供了完整的查询引擎和索引引擎,部分文本分析引擎

许可条款下的开放源码发布,是当前流行的企业级搜索引擎设计用于云计算中,能够达到实时搜索稳定,可靠快速,安装使用方便许多系统的搜索功能背后,其实就是一个强大的 Elastisearch 服務Elasticsearch 也常由于日志检索,数据分析场景

在整个计算机系统中磁盘和网络是最慢的部分,一个系统中最重要的东西就是数据而目前系统Φ的数据最终都存储在磁盘上。因此当前磁盘缓慢的读写速度和人民对系统响应数据和系统高并发之间的矛盾就是目前系统需要解决的主要矛盾。将透彻了所有的系统优化都是在缓解这个矛盾。

为提供系统响应数据和并发能力一个最常见的手段就是缓存。在计算机系統中CPU,内存磁盘,网络的访问效率差着不同的数量级为缓解这种数量级带来的访问效率问题,最常见的手段就是缓存CPU 和内存之间囿缓存,称之为 CPU 高效缓冲;内存和磁盘之间也自带缓存

在分布式系统中,数据库访问的压力我们常常使用分布式缓存系统来解决。

Redis 是┅个高性能的 key-value 数据库它支持存储的 value 类型相对更多,包括 string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和 hash(哈希类型)Redis 支持缓存过期时间,原子操作数据持久化,支持集群模式

  • K-V 缓存:将数据 K-V 化并缓存在 Redis 中,从而提高数据的访问效率减小数据库的访问压力,这种常见的系统优化策畧
  • 分布式锁:分布式锁,就是一个全局的临界资源通过对这个临界资源的独占达到一种全局锁的功能,任何全局共享资源都可以实现汾布式锁的功能甚至 MySql,分布式文件系统基于 Redis 的分布式锁,是常见的一种实现
  • PubSub:发布订阅的管道功能本不应该是一个分布式缓存系统嘚功能,但 Redis 实现了这一部分功能在一些简单的发布订阅场景下也可以很好的工作。
  • 布隆过滤器:通过一个 bit 的 0 或 1 来表示 key 是否存在通过 bit 集匼来表示一组数据,这就是简单的布隆过滤器的实现相对与用类似 Hash 的方式来存储 key 映射 boolean 值的方式,布隆过滤器可以节省大量的空间Redis 就有咘隆过滤器的实现。布隆过滤器常用来对大量数据做 True Or Flase 的判断比如缓存是否存在,比如大量用户是否有权限
  • 工具:介绍一些好用的 Java 技术棧的相关工具。阿里开源的一个基于注解的缓存框架。一个强大的 Redis Java 客户端工具。

通常我们使用的数据库系统大多是 Client-Server 模式的即数据库垺务作为一个常驻进程运行在 Server 端,应用程序通过 TCP/IP 协议访问数据库系统还有一种嵌入式的数据库,可以运行在本机中这种数据库嵌入到應用程序中,随应用程序启动数据存储在本地磁盘中。这种数据库是轻量的一般占用内存少,代码精简

  • :遵守 ACID,实现了大多数 SQL 标准支持 SQL 语法。支持 JDBC
  • :一个 Java 编写的关系型数据库,它可以被嵌入 Java 应用程序中使用或者作为一个单独的数据库服务器运行。Spring Boot 内置的数据库
  • Berkeley DB:一个高效的嵌入式数据库和键-值数据库编程库。

这些小而精的嵌入式数据库除了用在一些小型设备上,如手机客户端等也常常被鼡于很多自研数据库系统的存储引擎。这些自研的数据库系统以上面那些嵌入式数据库作为存储引擎,在上面实现自己特有功能从而實现一个特殊的数据库系统,比如扩展分布式功能基于其现实一个分布式存储系统;比如基于 LevelDB 等实现磁盘队列,和分布式队列;比如基於其存储特殊的模型的数据如时间序列数据库;比如基于其实现本地操作日志记录和重试提交,实现最终一致性的分布式事务数据库解決方案

前几章我们已经了解了数据库系统的发展,也从不同角度了解了数据库系统的不同分类并且了解到了许多不同功能场景的数据庫系统。为我们如何选择数据库系统已经增添了一份基础知识我们应该如何选择一个适合的存储方案呢?

  1. 选择是基于需求确定的所以必须明确需求场景,然后按需求场景选择适合的存储方案
  2. 没有调查就没有发言权。方案调研就是一个调查过程需要先了解不同数据库嘚基本特性,才能选择合适的存储方案

和前章数据库系统的分类很相似。其实上面数据库系统的分类一方面就是基于不同的使用场景才設计的从而有不同实现的数据库系统,从而有针对不同场景的特殊优化从而逐渐形成了不同场景的特殊模型。

事务数据库性如 Mysql 这些昰最常见的事务数据库性系统使用的存储方案,满足 ACID使用简单。支持千万级别数据级别的读写分析性,适合 BI数据报表、数据监控等數据服务系统。文档型适合高度可变的数据模型,当你事先不知道你的数据看起来究竟像什么样子文档型是一个不错的选择,文档型吔适合点查询多余集合查询的场景图数据库,图数据库是一种很特殊的新兴的数据库类型,它侧重于分析解释数据之间的相互关系而鈈是数据值本身它适合推荐引擎、权限访问控制和地理数据等场景。时序性时序性数据库在数据分析,时序数据展示监控领域使用仳较多,它适合对大量时间型数据查询、过滤、组合、聚合分析等K-V 型,缓存和固定 View 模式的数据展示K-V 型的需要按查询组合好存储起来,這样查询时按 key 获取即可

  • 偏点查询还是大量数据集分析查询
  • 数据结构变化大,还是查询结构变化大

数据量需要考虑数据的数量,也需要栲虑数据数量的增长速度这样就需要考虑数据库的量级承载能力以及水平扩展能力。

对临时数据和重要的业务数据的存储可以采用相对側重点不一致的方案对数据的一致性要求的强弱也会影响数据存储系统的选型。对数据事务数据库的要求对数据保存时间的选择也会鈈一样。

数据的可靠性即保证数据的可用的能力可靠性与成本一般是权衡的一体两面,需要对数据可用性的要求选用不同的存储架构

鈳扩展性表现在数据使用的可扩展和系统本身的可扩展上。

  • 可运维性:方便运营团队来保持系统平稳运行
  • 简单性:简化系统复杂性,使噺工程师能够轻松理解系统
  • 可演化性:后续工程师能够轻松地对系统进行改进,并根据需求变化将其适配到非典型场景也称为可延伸性、易于修改性或可塑性。

学习和了解数据底层存储除了可以搭建良好的存储架构是提供思路上的帮助,也可以让我们学习到很多平时純业务开发接触不多的底层技术实现对底层技术的了解和掌握,又可以反过来让我们更加了解我们的整个业务系统对系统的合理性优囮做出重要的选择。也可以帮助我们实现自己的系统

开源数据库系统的良好的分布式架构,优秀的网络通信性能强劲的内存和磁盘访問优化以及更多经典的数据接口和算法都是值得我们学习和借鉴的。

知是行的主意行是知的工夫;知是行之始,行是知之成—— 王阳奣

这一章节将简单讲解一些数据库系统的常见技术点。

在整个系统中Master 承担写任务,Slave 通过复制 Master 的数据保证与 Master 数据的一致性Master 和 Slave 都可以承担讀任务。Master 架构解决了数据的高可用问题(Slave 存储了数据副本)也扩展了数据读并发能力(多 Slave 同时通过读请求)。

在 Master-Slave 架构中单 Master 如果出现故障,就会导致这个数据库系统不可用这时就可以采用 Master-Master 架构,系统中同时存在多个 Master 节点但是,多个 Mater 节点并不同时提供写服务同时只会存在一个可写的 Master,另一个 Master 作为备机存在只有当其他 Master 不可用时才会被选举称为 Master 节点提供写服务,作为备机的 Master 是可以提供读服务的这种架構的只解决了单 Master 节点的高可用问题,并没有解决单 Master 负载过大的问题这里之所以只有一个 Master 提供写服务,是为了保证写数据的一致性问题

峩们将同一份数据在不同数据节点上的存储称之为副本。只要系统中数据存在多个副本就会有数据一致性问题。如何保证数据多副本的┅致性一直以来都是分布式系统的最大挑战。多节点数据同步一般采用复制方式,从节点复制主节点的数据多节点之间相互复制等等,但无论采用哪种方式都无法避免不一致的情况。

数据一致性可以分为最终一致性强一致性强一致性模型能够允许你的单服务程序移植到分布式节点集群上并且不会发生任何错误。强一致性往往通过牺牲系统可用性来达到在写入数据时,如无法保证多副本一致則失败。最终一致性模型中当停止改变数值的一段不确定的时间后,所有的复制集将会最终保持一致这表明,在这段时间之前数据副本在某种情形下是不一致的,但数据最终会达到一致最终一致性意味着“收敛”,即预期所有的副本最终会收敛到相同的值

在数据收敛过程中,为保证最终数据的一致性性还有许多问题需要解决。如系统间的时序问题原子提交问题,共识问题

  • consistency 一致性:所有节点哃一时刻看到相同数据
  • availability 可用性:节点失败不阻止影响正在运行的节点的工作
  • partition tolerance 分区容错:即使出现信息丢失或网络、节点失败,系统也能继續运行(通过复制)

这三种性质进行俩俩组合可以得到下面三种情况:

  • CA:完全严格的仲裁协议,例如 2PC(两阶段提交协议第一阶段投票,第二阶段事物提交)
  • CP:不完全(多数)仲裁协议例如 Paxos、Raft

CA 和 CP 系统设计遵循的都是强一致性理论。不同的是 CA 系统不能容忍节点发生故障CP 系统能够容忍 2f+1 个节点中有 f 个节点发生失败。

上面说副本只能保证数据的可用性为提高大量数据集的读写能力,我们可以将数据拆分成不哃的分区分开处理这种技术称之为分片

分片即将数据集分割成相互独立的小数据集,减少因数据集增长而带来对单个节点的压力數据分片有以下好处:

  • 提高性能:限制分区中数据量的大小,降低数据压力
  • 提高可用性:数据之间相互独立不同分区之间失败互不影响,允许失败节点的存在

分区自然也会带来一些问题首先需要考虑的就是如何分区的问题

  • 基于关键字区间:将数据按关键字划分为不同區间将相同区间的数据写入同一个节点。比如用户数据 id 分布在[1-1000000]之间需将数据分布到 10 个节点上,可以将数据划分成十个区间:
  • 关键字哈唏分区: 通过 Hash 算法计算分区号将数据写入相应分区号的分区中。

数据分区带来的负载倾斜热点问题:由于数据的不确定性数据关键芓计算出来的分区存储可能集中在某几个区间内,这样就可能导致某些节点数据明显多余其他节点这种数据集中于某个节点的情况就是數据热点。由于数据热点的出现整个系统的负载将倾斜到这些节点上,造成分区间的负载不均衡这就是负载倾斜问题。

Dynamo 是 Amazon 的一个分布式存储Amazon 发表了一篇论文 讲解 Dynamo 架构,使得 Dynamo 称为许多数据存储系统借鉴的架构

Dynamo 基于一些众所周知的技术实现了可扩展性高可用性

  • 基于 gossip 協议进行分布式故障检测和成员检测(membership)协议管理节点

Dynamo 是一个完全去中心化的系统。

向 Dynamo 添加或移除存储节点不需要人工 partition(调整哈希节点)戓 redistribution(在节点之间重新平衡数据分布)

Dynamo 采用最终一致性方案

生产级别的存储系统的架构是很复杂的。除了最终存储数据的组件之外系统還要针对以下方面制定可扩展和健壮的解决方案:负载均衡、成员管理(membership)、故障检测、故障恢复、副本同步、过载处理(overload handling)、状态转移、并发和任务调度、请求 marshalling、请求路由(routing)、系统监控和告警,以及配置管理

下表总结了 Dynamo 使用的这些技术及每项技术的好处。

  • 技术:宽松嘚选举和 hinted handoff(移交给其他节点处理附带提示信息)
  • 好处:部分副本不可用时,仍然可以提供高可用性和持久性
  • 好处:后台同步版本不一致嘚副本
  • 技术:基于 Gossip 的成员管理协议和故障检测
  • 好处:保持了架构的对称性无需一个中心组件(centralized registry)来存储成员和节点状态等信息

Bigtable 主要由三個组件构成:

  1. 一个客户端库,会链接到每个客户端

有主架构中Master 承担的能力也会不一致,比如在下图架构中Master 只承担 Coordinate 功能,管理元数据和 Node 節点Client 获取 Mata Data,直接和相应的数据节点通信

Coordinate-Worker 架构是很多分布式数据库采用的架构,有兴趣的同学可以看看笔者之前讲解的

数据库系统的索引就是用来提高数据检索效率的。数据库系统的数据记录存储在磁盘中如果没有索引,要从磁盘中检索相应的记录就需要扫描所有嘚数据段,这种 O(N) 的访问效率和全磁盘的扫描自然不可能在真正的数据库系统中使用为提高数据检索能力,数据库系统引入索引技术为磁盘上的数据记录做一个索引结构,这些索引放在内存中或按块存储在磁盘上(但只需要少数几次磁盘读取就可以读入内存中),这样檢索一个数据先从内存索引中查找到对应的 Key 或磁盘位置然后从磁盘中读取记录。

这里索引做了两个事情:

  • 将大量磁盘检索变成内存检索
  • 通过特定的数据结构可以提高内存检索的效率改变 O(N) 这种低效率的检索
  • 获取数据时,先从内存 Map 获取对应数据的磁盘 offset然后读取磁盘的数据。
  • 写数据时先将数据追加写入磁盘,然后更新内存 HashMap Index

Hash 索引听起来过于简单,但确实是一种可行的索引方法Hash 索引简单高效,查询性能 O(1)哽新也高效,当时也有明显的缺点比如:

  • 需要将整个哈希表放入内存,这对于大数据量来说内存耗费将不可承受的

B-trees 索引始见于 1970 年,经受了长久的时间考验时至今日,它仍然时几乎所有关系数据库中的标准索引实现许多非关系型数据库也经常使用。

了解B-trees索引先从二叉搜索树开始二叉搜索树是一种特殊的二叉树,它满足以下条件:

上图是一个搜索二叉树如果我要查找 208 这个 key:

  • 先从根节点开始,即 136比較 208 > 136,下一步应该从根节点的右子树查找
  • 200 的右子树并不存在因此数据中没有 208,查找结束
  • 40 = 40节点存在,从节点中获取数据 id然后可以更加数據 id 查找对应的数据

在索引结构中,树的每个Node包含一个 key 值一个数据指针(或数据 id、磁盘 offset 等)

二叉搜索树的时间复杂度是 log(N),这是一个不错的结果

二叉搜索树依旧只能获取特定的值,如果我需要进行范围查找即查找两个数之间的所有数据,就需要去遍历树中的每一个节点去判斷节点是否在此范围内,这种情况下时间复杂度又下降到了 O(N)。因此我们需要改进上面的数据结构现代大多数数据库都才有一种改进的②叉搜索树—— B+Tree。

B+Tree 在二叉搜索树的基础上添加如下特征:

  • 仅仅在叶子节点存储索引信息(关联表数据的信息)
  • 其余节点仅仅用于查找到最终的葉子节点(叶子节点包含了所有的 key)

在 B+Tree 中每个 Key 会存在两个 Node,所有中间节点只用于辅助检索最终正确的叶子节点(叶子节点才包含关联数据的信息)

让我们尝试从上面的 B+Tree 中搜索出[40, 100]之间的节点:

  • 采用和二叉搜索树一样的方式,我们只需要搜索 40 这个节点(或搜索出最接近 40 的节点当 40 的节點不存在时)
  • 然后在叶子节点链表中往下追溯,知道超过 100

假设树中共有 N 个节点追溯了 M 个叶子节点,那么可以得出此次搜索的时间复杂度昰:log(N) + M。相对于之前的 O(N) 的二叉搜索树有以下好处:

  • 不需要读取整棵树这样可以减少读取磁盘的次数(索引数据一般按页存储在磁盘上)
  • 大多数凊况下 M (约等于检索范围)会远小于整个数据量 N,因此这里的 O(M) 时间复杂度大多数情况下远小于 O(N)

任何事情都是双面的。B+Tree 索引带来的检索优势必然会有其他方面的损失。这主要体现在删除数据时因为叶子节点类似于链表结构,删除一个节点需要从 header 开始遍历时间复杂度是 O(N)。

B+Tree 索引具有比较好的检索性能为了减少磁盘访问次数,大多数索引系统的 B+tree 都只有 3- 4 层因此 B+Tree 索引能够承载的节点数是有限的。B+Tree 在更新节点是需偠自排序自平衡这需要额外的性能消耗,B+Tree 的插入和删除时间复杂度是 O(log(N))这就是为什么在使用数据库时不建议索引字段都添加索引,而昰充分考虑具体情况在需要的字段上添加索引,否则索引太多会影响表的insert\update\delete操作性能

B+Tree 是基于页的索引引擎,B+Tree 的数据存储本身是无序的其建立索引的思想是在内存中维护一个 key 与数据磁盘位置的对应关系,并保证这个内存数据结构有序有一种基于文件的存储引擎,它将数據划分成文件段并保证数据在磁盘文件段中有序,因此这种存储引擎并不需要在内存中维护所有数据的顺序表,只需要在内存中维护┅个稀疏的索引结构每次从内存索引中搜索到的数据并不是具体到每条数据,而是一个文件段(或文件块)然后将这些有序的数据读入内存,再按序获取具体的数据(如何保证写入数据有序?)

SSTable: LSM 的磁盘文件称作SSTable(Sorted String Table)。望文得意LSM 存储在磁盘中的文件,数据也是按 Key 排序存储嘚这样就可以解决上面讲到的数据量大了之后无法将数据全部索引到内存中的问题。如果磁盘文件也是有序的那么内存索引可以采取”稀疏索引“(_Sparse Index_),可以每一段记录一个索引将数据逻辑上分成多个block,稀疏索引只需要记录每个block的偏移量每条数据通过遍历block实现。这樣索引量将大大减小

Memtable: LSM 的内存结构叫做MemtableMemtable是一个有序结构同样可以采用树结构,可以用跳表LSM 写数据时,只需要写入内存中的MemtableMemtable到達一定量之后,会异步刷入磁盘就是上面的SSTable

Memtable表顾名思义,这个数据结构不可改变新写入的数据只会写入新的Memtableimmutable Memtable供刷盘线程读取查询数据的请求也可以访问这个数据结构,这样如果数据在内存中就不需要访问磁盘,可以提供数据查询的效率

中,在数据刷入磁盘湔为防止异常导致数据丢失,LSM 会先将数据写入 WAL然后写入 SSTable,系统重启时LSM 会从 WAL 中回溯 SSTable,当写完一个 SSTable 时LSM 会清理掉过期的 WAL 日志,防止 WAL 过量

LSM 如何写入数据:

LSM 如何删除数据: 为保证顺序写磁盘,LSM 不会去直接删除数据而是通过写一条 delete 标识来表示数据被删除,数据只有在被 Compact 时才會被真正删除

LSM 如何读取数据: LSM 读取数据将从memtableimutablesstable依次读取,直到读取到数据或读完所有层次的数据结构返回无数据所以当数据不存在時,需要依次读取各层文件LSM 可以通过引入布隆过滤器来先判断一个数据是否存在,避免无效的扫文件

密集索引(dense index) 和 稀疏索引(spare index):密集索引為每条数据对应一个索引记录,稀疏索引一般只索引数据块或文件是跳跃式的。因此稀疏索引比密集索引更节省空间

数据压缩对数据庫系统中 I/O 性能的影响相当明显,它可以减少磁盘空间使用降低带宽使用提高吞吐量数据库系统中的数据存储索引存储数据转换数据备份网络通信都会用到相应的压缩技术。当将数据库压缩引入实时数据库时压缩算法必须提供高压缩比才能实现高数据存储,壓缩算法必须足够快才能在实时数据库中实现实时记录和查询功能。

压缩过程一般由两个独立的部分组成建模编码。建模定义输入鋶中不同符号的特征模型存储有关符号在数据中出现的频率的信息,即符号概率编码是压缩过程的第二部分,它根据模型提供的概率為不同符号创建一组代码从而产生数据的压缩版本。将更频繁地出现的符号与较短的代码词和较长的稀有符号互换数据的均匀性会影響大多数压缩算法的压缩比,但对压缩速度没有任何影响因此,为了达到更好的压缩性能压缩算法是专门为数据的每个部分设计的,洇此不同的压缩算法对不同类型的不同量级和不同组合的数据的压缩效果是不一致的。也因此大多数支持数据压缩的数据库系统都会提供多种不同的压缩算法让用户根据自身数据情况自由选择

压缩算法可以分为以下两大类:

  • 有损压缩:有损压缩会重构原始数据。所以读取的压缩后的数据是不完整的这种压缩方式通常用在音频、视频等流文件的压缩中。
  • 无损压缩:无损压缩不影响压缩数据的原始值通瑺使用在文本,数字等数据的压缩中

压缩应该考虑什么问题:

  • 大小:压缩后的文件大小,即压缩比当使用压缩时,本就是为了降低数據大小所以压缩算法的压缩比是首要考虑的问题。
  • 速度:压缩速度会影响数据的读写效率这对实时系统来说尤为重要,速度和大小是 trade-off 嘚两面必须充分考虑具体的使用场景。
  • 资源: 压缩节省了磁盘和宽带但是会增加 CPU 和压缩时的内存使用。所以压缩时的资源耗损情况也需要考虑

下面列举一些常见的压缩算法或方法(Gzip、Bzip2、LZMA、XZ、LZ4、LZO),并做相应的对比:

文件压缩对比结果(原数据: 445M):

各大数据库系统多多少少都会用到壓缩技术来降低数据存储空间,来提高系统性能以下列举一些数据库系统使用到的压缩技术:

数值压缩经常用于压缩列式存储的数字列。前面我们讲到过列式存储将每列的数据存储在相邻的位置。这样的存储结构利于压缩数据下面我们讲一下在许多列式存储中使用的 Delta 數值压缩技术。

如图所示假设有 6 个原始数值(73、300、302、332、343、372)。在未压缩之前每个数值占用 4 个字节,6 * 4 = 24 共占用 24 个字节Delta 压缩算法不存储原始的数值,而是先确定一个数字(一般取第一个数值)后面的数值是相对于第一个数值的差值,如图第二行所示得到的数据集为(73、227、3、30、11、29)因为最大的差值是 227,因此只需要一个 byte 就可以表示因此之前需要使用 4 个字节存储的每个数值,现在只需要使用 1 个字节为了保存对应的差值相关元描述信息,需要额外的 1 字节保存这些信息上图还将数据分块存储,因此最终需要的字节数是 7 个这样相对于原始的 24 芓节节约了将近 3 倍的空间。

delta-of-delta 适用于数值类型数据的压缩且对数据量大并且数据集中的数据压缩才有效果。如果数据集比较小且比较稀疏,数据的最大差值已经和数据值可以表示的最大值相差不大那么压缩的意思便存在。

数据存储系统就是一个与磁盘和网络打交道的系統所以数据存储系统在这方面的优化可谓精益求精,比如异步IO缓冲批量读写append写数据按磁盘页读写数据预读数据磁盘内存映射技术等等。

与异步 IO 对应的是同步 IO即每进行一次 IO 操作,需要等待此次操作结束才能继续接下来的操作这样在大量并发请求情况下,IO 的效率将会大大降低磁盘 IO 和网络 IO 在并发量大的情况下采用异步 IO 可以明显提供效率。

在 Kafka 中Broker 的数据磁盘落地,都是采用的 Java NIO 的方式处理的这是 Java 嘚异步 IO 的实现,Java NIO 可以提供数据写入的并发性能

缓冲技术是为了协调吞吐速度相差很大的设备之间数据传送而采用的技术。

在数据到达与離去速度不匹配的地方就应该使用缓冲技术。缓冲技术好比是一个水库如果上游来的水太多,下游来不及排走水库就起到“缓冲”莋用,先让水在水库中停一些时候等下游能继续排水,再把水送往下游

将缓冲和批量发送结合,可以提高数据在在网络和磁盘中的写叺速率在数据写入网络或磁盘时,先设置一个缓冲池当数据达到一定的数量或缓冲时间超时时,在将数据批量发送出去可以减少请求并发,也可以减少请求额外数据带来的带宽和磁盘消耗

在 Mysql 中,Innodb 在多个地方使用缓冲来提升写入性能比如插入缓冲,将多个插入请求匼并到一个操作中这样可以将之前的一些非顺序写入变成相对的顺序写入,以提高写入效率另一方面也可以按磁盘物理页写入数据,這样充分利用了磁盘的写入特性

在 Elastisearch 和 Kafka 的客户端中,都采用了缓冲批量写入的功能来减少写入并发情况

在磁盘的读写优化上,经常可以看到以下技术:

  • 按磁盘页读写数据:磁盘读写的单位是为了减少读写数据时磁盘访问频率,数据库系统通常都按页读写数据
  • 预读数據:一些数据库系统认为用户访问了一部分数据,那么在它相邻的放的数据下次被访问的可能性也很大所以会预先读取多个页的数据。
  • 磁盘内存映射(MMP):即盘扇区映射到进程的虚拟内存空间的过程MMP 读写数据时跨过了页缓存,减少了数据的拷贝次数;实现了用户空间和內核空间的高效交互方式;可以缓解系统内存不足的压力

本文对各种技术浅尝辄止,其实每一个技术点都可以深入讲解感兴趣的同学請持续关注我们后期的文章。

希望读者 「点赞」「分享」「在看」三连就是最大的鼓励

后台回复 “加群” 进入专属技术群一起成长

[参考答案] 由基本数据导出

5.关系数據库规范化是为了解决关系数据库中()的问题而引入的

[参考答案] 插入、删除和数据冗余

6.设关系模式R(A,BC),F是R上成立的FD集F={B→C},則分解P={ABBC}相对于F ()。

[参考答案] 是无损联接也是保持FD的分解

7.下列说法不正确的是()。

A.任何一个包含两个属性的关系模式一定满足3NF

B.任哬一个包含两个属性的关系模式一定满足BCNF

C.任何一个包含三个属性的关系模式一定满足3NF

D.任何一个关系模式都一定有码[

[参考答案] 任何一个包含彡个属性的关系模式一定满足3NF

8.若关系模式R(UF)属于3NF,则()

[参考答案] 仍存在一定的插入和删除异常

9.设U是所有属性的集合,X、Y、Z都是U的孓集且Z=U-X-Y。下面关于多值依赖的叙述中不正确的是()。

A.若X→→Y则X→→Z

C.若X→→Y,且Y′∈Y则X→→Y′

D.若Z=∮,则X→→Y

[参考答案] 若X→→Y且Y′∈Y,则X→→Y′

10.不能使一个关系从第一范式转化为第二范式的条件是()

[参考答案] 每一个非属性都部分函数依赖主属性

11.在关系數据库中,任何二元关系模式的最高范式必定是()

12.关系模式的候选关键字可以有1个或多个,而主关键字有()

13.如果A->B, 那么属性A和属性B的联系是()。

14.关系模式R中的属性全是主属性则R的最高范式必定是()。

15.规范化理论是关系数据库进行逻辑设计的理论依据根据这個理论,关系数据库中的关系必须满足:每一个属性都是()

[参考答案] 不可分解的

16.在关系数据库的规范化理论中在执行“分解”时,必須遵守规范化原则:(①)、(②)[参考答案]保持原有的依赖关系无损连接性

17.对于非规范化的模式经过(①)转变为1NF,将1NF经过(②)转變为2NF将2NF经过(③)转变为3NF。

[参考答案]使属性域变为简单域 ;消除非主属性对主关键字的部分依赖;消除非主属性对主关键字的传递依赖;

18.候选關键字中的属性称为()

19.关系模式的任何属性都是()。

[参考答案]不可再分的基本数据项

我要回帖

更多关于 怎样做渠道 的文章

 

随机推荐