chapter 3 still in progress

This commit is contained in:
Yin Gang 2021-07-26 22:17:36 +08:00
parent a40ce46024
commit 1ec79062e7

34
ch3.md
View File

@ -308,11 +308,11 @@ B树在数据库体系结构中是非常根深蒂固的为许多工作负载
索引中的键是查询搜索的内容,而其值可以是以下两种情况之一:它可以是所讨论的实际行(文档,顶点),也可以是对存储在别处的行的引用。在后一种情况下,行被存储的地方被称为**堆文件heap file**,并且存储的数据没有特定的顺序(它可以是仅追加的,或者可以跟踪被删除的行以便用新数据覆盖它们后来)。堆文件方法很常见,因为它避免了在存在多个二级索引时复制数据:每个索引只引用堆文件中的一个位置,实际的数据保存在一个地方。
在不更改键的情况下更新值时堆文件方法可以非常高效只要新值不大于旧值就可以覆盖该记录。如果新值更大情况会更复杂因为它可能需要移到堆中有足够空间的新位置。在这种情况下要么所有的索引都需要更新以指向记录的新堆位置或者在旧堆位置留下一个转发指针【5】。
在某些情况下从索引到堆文件的额外跳跃对读取来说性能损失太大因此可能希望将索引行直接存储在索引中。这被称为聚集索引。例如在MySQL的InnoDB存储引擎中表的主键总是一个聚簇索引,二级索引用主键而不是堆文件中的位置【31】。在SQL Server中可以为每个表指定一个聚索引【32】。
在某些情况下从索引到堆文件的额外跳跃对读取来说性能损失太大因此可能希望将索引行直接存储在索引中。这被称为聚集索引。例如在MySQL的InnoDB存储引擎中表的主键总是一个聚集索引,二级索引则引用主键而不是堆文件中的位置【31】。在SQL Server中可以为每个表指定一个聚索引【32】。
**聚集索引clustered index** (在索引中存储所有行数据)和 **非聚集索引nonclustered index** (仅在索引中存储对数据的引用)之间的折衷被称为 **包含列的索引index with included columns**或**覆盖索引covering index**其存储表的一部分在索引内【33】。这允许通过单独使用索引来回答一些查询这种情况叫做索引 **覆盖cover** 了查询【32】。
与任何类型的数据重复一样,聚和覆盖索引可以加快读取速度,但是它们需要额外的存储空间,并且会增加写入开销。数据库还需要额外的努力来执行事务保证,因为应用程序不应该因为重复而导致不一致。
与任何类型的数据重复一样,聚和覆盖索引可以加快读取速度,但是它们需要额外的存储空间,并且会增加写入开销。数据库还需要额外的努力来执行事务保证,因为应用程序不应看到任何因为重复而导致的不一致。
#### 多列索引
@ -339,23 +339,23 @@ SELECT * FROM restaurants WHERE latitude > 51.4946 AND latitude < 51.5079
例如全文搜索引擎通常允许搜索一个单词以扩展为包括该单词的同义词忽略单词的语法变体并且搜索在相同文档中彼此靠近的单词的出现并且支持各种其他功能取决于文本的语言分析。为了处理文档或查询中的拼写错误Lucene能够在一定的编辑距离内搜索文本编辑距离1意味着添加删除或替换了一个字母【37】。
正如“[在SSTables中创建LSM树](#在SSTables中创建LSM树)”中所提到的Lucene为其词典使用了一个类似于SSTable的结构。这个结构需要一个小的内存索引告诉查询在排序文件中哪个偏移量需要查找。在LevelDB中这个内存中的索引是一些键的稀疏集合但在Lucene中内存中的索引是键中字符的有限状态自动机类似于trie 【38】。这个自动机可以转换成Levenshtein自动机它支持在给定的编辑距离内有效地搜索单词【39】。
正如“[在SSTables中创建LSM树](#在SSTables中创建LSM树)”中所提到的Lucene为其词典使用了一个类似于SSTable的结构。这个结构需要一个小的内存索引告诉查询需要在排序文件中哪个偏移量查找键。在LevelDB中这个内存中的索引是一些键的稀疏集合但在Lucene中内存中的索引是键中字符的有限状态自动机类似于trie 【38】。这个自动机可以转换成Levenshtein自动机它支持在给定的编辑距离内有效地搜索单词【39】。
其他的模糊搜索技术正朝着文档分类和机器学习的方向发展。有关更多详细信息请参阅信息检索教科书例如【40】。
#### 在内存中存储一切
本章到目前为止讨论的数据结构都是对磁盘限制的回答。与主内存相比磁盘处理起来很尴尬。对于磁盘和SSD如果要在读取和写入时获得良好性能则需要仔细地布置磁盘上的数据。但是我们容忍这种尴尬因为磁盘有两个显著的优点它们是耐用它们的内容在电源关闭时不会丢失并且每GB的成本比RAM低。
本章到目前为止讨论的数据结构都是对磁盘限制的回答。与主内存相比磁盘处理起来很尴尬。对于磁盘和SSD如果要在读取和写入时获得良好性能则需要仔细地布置磁盘上的数据。但是我们容忍这种尴尬因为磁盘有两个显著的优点它们是持久它们的内容在电源关闭时不会丢失并且每GB的成本比RAM低。
随着RAM变得更便宜每GB的成本价格被侵蚀了。许多数据集不是那么大,所以将它们全部保存在内存中是非常可行的,可能分布在多个机器上。这导致了内存数据库的发展。
随着RAM变得更便宜每GB成本的论据被侵蚀了。许多数据集不是那么大,所以将它们全部保存在内存中是非常可行的,可能分布在多个机器上。这导致了内存数据库的发展。
某些内存中的键值存储如Memcached仅用于缓存在重新启动计算机时丢失的数据是可以接受的。但其他内存数据库的目标是持久性可以通过特殊的硬件例如电池供电的RAM将更改日志写入磁盘将定时快照写入磁盘或通过复制内存来实现,记忆状态到其他机器
某些内存中的键值存储如Memcached仅用于缓存在重新启动计算机时丢失的数据是可以接受的。但其他内存数据库的目标是持久性可以通过特殊的硬件例如电池供电的RAM将更改日志写入磁盘将定时快照写入磁盘或者将内存中的状态复制到其他机器上
内存数据库重新启动时,需要从磁盘或通过网络从副本重新加载其状态(除非使用特殊的硬件)。尽管写入磁盘,它仍然是一个内存数据库,因为磁盘仅用作耐久性附加日志,读取完全由内存提供。写入磁盘也具有操作优势:磁盘上的文件可以很容易地由外部实用程序进行备份,检查和分析。
内存数据库重新启动时,需要从磁盘或通过网络从副本重新加载其状态(除非使用特殊的硬件)。尽管写入磁盘,它仍然是一个内存数据库,因为磁盘仅出于持久性目的进行日志追加,读取完全由内存提供。写入磁盘也具有运维优势:磁盘上的文件可以很容易地由外部实用程序进行备份,检查和分析。
诸如VoltDBMemSQL和Oracle TimesTen等产品是具有关系模型的内存数据库供应商声称通过消除与管理磁盘上的数据结构相关的所有开销他们可以提供巨大的性能改进【41,42】。 RAM Cloud是一个开源的内存键值存储器具有持久性对存储器中的数据以及磁盘上的数据使用日志结构化方法【43】。 Redis和Couchbase通过异步写入磁盘提供了较弱的持久性。
反直觉的是,内存数据库的性能优势并不是因为它们不需要从磁盘读取的事实。即使是基于磁盘的存储引擎也可能永远不需要从磁盘读取,因为操作系统缓存最近在内存中使用了磁盘块。相反它们更快的原因在于省去了将内存数据结构编码为磁盘数据结构的开销。【44】。
反直觉的是,内存数据库的性能优势并不是因为它们不需要从磁盘读取的事实。即使是基于磁盘的存储引擎也可能永远不需要从磁盘读取,因为操作系统在内存中缓存了最近使用的磁盘块。相反它们更快的原因在于省去了将内存数据结构编码为磁盘数据结构的开销。【44】。
除了性能内存数据库的另一个有趣的领域是提供难以用基于磁盘的索引实现的数据模型。例如Redis为各种数据结构如优先级队列和集合提供了类似数据库的接口。因为它将所有数据保存在内存中所以它的实现相对简单。
@ -367,19 +367,19 @@ SELECT * FROM restaurants WHERE latitude > 51.4946 AND latitude < 51.5079
## 事务处理还是分析?
在早期业务数据处理过程中,一次典型的数据库写入通常与一笔 *商业交易commercial transaction* 相对应:卖个货,向供应商下订单,支付员工工资等等。但随着数据库应用至那些不涉及到钱的领域,术语 **交易/事务transaction** 仍留了下来,用于指代一组读写操作构成的逻辑单元。
在早期业务数据处理过程中,一次典型的数据库写入通常与一笔 *商业交易commercial transaction* 相对应:卖个货,向供应商下订单,支付员工工资等等。但随着数据库应用至那些不涉及到钱的领域,术语 **交易/事务transaction** 仍留了下来,用于指代一组读写操作构成的逻辑单元。
事务不一定具有ACID原子性一致性隔离性和持久性属性。事务处理只是意味着允许客户端进行低延迟读取和写入 —— 而不是批量处理作业,而这些作业只能定期运行(例如每天一次)。我们在[第7章](ch7.md)中讨论ACID属性在[第10章](ch10.md)中讨论批处理。
即使数据库开始被用于许多不同类型的博客文章,游戏中的动作,地址簿中的联系人等等,基本访问模式仍然类似于处理业务事务。应用程序通常使用索引通过某个键查找少量记录。根据用户的输入插入或更新记录。由于这些应用程序是交互式的,因此访问模式被称为 **在线事务处理OLTP, OnLine Transaction Processing**
即使数据库开始被用于许多不同类型的数据,比如博客文章的评论,游戏中的动作,地址簿中的联系人等等,基本访问模式仍然类似于处理商业交易。应用程序通常使用索引通过某个键查找少量记录。根据用户的输入插入或更新记录。由于这些应用程序是交互式的,这种访问模式被称为 **在线事务处理OLTP, OnLine Transaction Processing**
但是,数据库也开始越来越多地用于数据分析,这些数据分析具有非常不同的访问模式。通常,分析查询需要扫描大量记录,每个记录只读取几列,并计算汇总统计信息(如计数,总和或平均值),而不是将原始数据返回给用户。例如,如果您的数据是一个销售交易表,那么分析查询可能是:
* 一月份每个商店的总收入是多少?
* 在最近的推广活动中卖了多少香蕉?
* 在最近的推广活动中卖了多少香蕉?
* 哪个牌子的婴儿食品最常与X品牌的尿布同时购买
这些查询通常由业务分析师编写,并提供给帮助公司管理层做出更好决策(商业智能)的报告。为了区分这种使用数据库的事务处理模式,它被称为**在线分析处理OLAP, OnLine Analytice Processing**。【47】。OLTP和OLAP之间的区别并不总是清晰的但是一些典型的特征在[表3-1]()中列出。
这些查询通常由业务分析师编写,并提供给帮助公司管理层做出更好决策(商业智能)的报告。为了将这种使用数据库的模式和事务处理区分开,它被称为**在线分析处理OLAP, OnLine Analytice Processing**。【47】。OLTP和OLAP之间的区别并不总是清晰的但是一些典型的特征在[表3-1]()中列出。
**表3-1 比较交易处理和分析系统的特点**
@ -431,17 +431,17 @@ TeradataVerticaSAP HANA和ParAccel等数据仓库供应商通常使用昂
通常情况下事实被视为单独的事件因为这样可以在以后分析中获得最大的灵活性。但是这意味着事实表可以变得非常大。像苹果沃尔玛或eBay这样的大企业在其数据仓库中可能有几十PB的交易历史其中大部分实际上是表【56】。
事实表中的一些列是属性,例如产品销售的价格和从供应商那里购买的成本(允许计算利润余额)。事实表中的其他列是对其他表(称为维表)的外键引用。由于事实表中的每一行都表示一个事件,因此这些维度代表事件的发生地点,时间,方式和原因。
事实表中的一些列是属性,例如产品销售的价格和从供应商那里购买的成本(允许计算利润余额)。事实表中的其他列是对其他表(称为维表)的外键引用。由于事实表中的每一行都表示一个事件,因此这些维度代表事件的发生地点,时间,方式和原因。
例如,在[图3-9](img/fig3-9.md)中,其中一个维度是已售出的产品。 `dim_product` 表中的每一行代表一种待售产品,包括**库存单位SKU**,说明,品牌名称,类别,脂肪含量,包装尺寸等。`fact_sales` 表中的每一行都使用外部表明在特定交易中销售了哪些产品。 (为了简单起见,如果客户一次购买几种不同的产品,则它们在事实表中被表示为单独的行)。
即使日期和时间通常使用维度表来表示,因为这允许对日期(诸如公共假期)的附加信息进行编码,从而允许查询区分假期和非假期的销售。
甚至日期和时间也通常使用维度表来表示,因为这允许对日期的附加信息(诸如公共假期)进行编码,从而允许查询区分假期和非假期的销售。
“星型模式”这个名字来源于这样一个事实,即当表关系可视化时,事实表在中间,由维表包围;与这些表的连接就像星星的光芒。
“星型模式”这个名字来源于这样一个事实,即当表关系可视化时,事实表在中间,由维表包围;与这些表的连接就像星星的光芒。
这个模板的变体被称为雪花模式,其中尺寸被进一步分解为子尺寸。例如,品牌和产品类别可能有单独的表格,并且 `dim_product` 表格中的每一行都可以将品牌和类别作为外键引用,而不是将它们作为字符串存储在 `dim_product` 表格中。雪花模式比星形模式更规范化但是星形模式通常是首选因为分析师使用它更简单【55】。
这个模板的变体被称为雪花模式,其中维度被进一步分解为子维度。例如,品牌和产品类别可能有单独的表格,并且 `dim_product` 表格中的每一行都可以将品牌和类别作为外键引用,而不是将它们作为字符串存储在 `dim_product` 表格中。雪花模式比星形模式更规范化但是星形模式通常是首选因为分析师使用它更简单【55】。
在典型的数据仓库中,表格通常非常宽事实表格通常有100列以上有时甚至有数百列【51】。维度表也可以是非常宽的因为它们包括可能与分析相关的所有元数据——例如`dim_store` 表可以包括在每个商店提供哪些服务的细节,它是否具有店内面包房,店面面积,商店第一次开的日期,最后一次改造的时间,离最近的高速公路的距离等等。
在典型的数据仓库中表格通常非常宽事实表格通常有100列以上有时甚至有数百列【51】。维度表也可以是非常宽的因为它们包括可能与分析相关的所有元数据——例如`dim_store` 表可以包括在每个商店提供哪些服务的细节,它是否具有店内面包房,店面面积,商店第一次开的日期,最后一次改造的时间,离最近的高速公路的距离等等。