在本章中,我们试图深入了解数据库如何处理存储和检索。 将数据存储到数据库时会发生什么,以及稍后再次查询数据时数据库会发生什么。
在高层次上,我们看到存储引擎分为两大类:针对事务处理(OLTP)进行优化的,以及针对分析(OLAP)优化的。 这些用例的访问模式之间存在很大差异:
OLTP系统通常面向用户,这意味着他们可能会看到大量的请求。 为了处理负载,应用程序通常只触及每个查询中的少量记录。 应用程序使用某种键请求记录,并且存储引擎使用索引来查找所请求键的数据。 磁盘寻道时间往往是这里的瓶颈。
数据仓库和类似的分析系统并不为人所知,因为它们主要由业务分析师使用,而不是由最终用户使用。 它们处理的查询量比OLTP系统少得多,但每个查询通常要求很高,需要在短时间内扫描数百万条记录。 磁盘带宽(不寻求时间)通常是这里的瓶颈,面向服务的存储是这种工作负载越来越流行的解决方案。
在OLTP方面,我们看到来自两大主流的存储引擎:
日志结构(log-structured)模式,只允许追加文件和删除过时的文件,但不会更新已写入的文件。 Bitcask,SSTables,LSM-trees,LevelDB,Cassandra,HBase,Lucene等都属于这一组。
就地更新(update-in-place)模式将磁盘视为一组可覆盖的固定大小页面。 B-树是这一哲学的最大例子,用于所有主要的关系数据库以及许多非关系数据库。
日志结构存储引擎是相对较新的发展。 他们的主要想法是,他们系统地将随机访问写入转换为顺序写入磁盘,由于硬盘驱动器和SSD的性能特点,可以实现更高的写入吞吐量。
在完成OLTP方面,我们通过一些更复杂的索引结构和为保留所有数据而优化的数据库进行了简要介绍。
然后,我们从存储引擎的内部绕开看看典型数据仓库的高级架构。 这一背景说明了为什么分析工作负载与OLTP差别很大:当您的查询需要在大量行上顺序扫描时,索引的相关性就会降低很多。 相反,非常紧凑地编码数据变得非常重要,以最大限度地减少查询需要从磁盘读取的数据量。 我们讨论了面向列的存储如何帮助实现这一目标。
作为一名应用程序开发人员,如果您掌握了关于存储引擎内部的知识,那么您就能更好地了解哪种工具最适合您的特定应用程序。 如果您需要调整数据库的调整参数,这种理解允许您设想一个更高或更低的值可能会产生什么效果。
尽管本章无法让您成为调优任何特定存储引擎的专家,但希望您能够为您提供足够的词汇和想法,以便您可以了解所选数据库的文档。