- 将文件保存在RAM或磁盘上,哪个更好?这取决于……
- 按原样写文件和压缩文件哪个更好?这取决于……
- 当一行发生更改时修改文件还是保留历史记录,哪种方法更好?这取决于……
- 以A或B格式存储数据,哪种更好?这取决于……
如何处理“视情况而定”
简单的方法是两者都做,例如以柱状和行状两种格式存储数据。通过这种方式,用户可以访问其中之一,或者其他更有意义的。当然,这个选择是有代价的。在这种情况下,数据需要存储两次——将优点和缺点结合起来。
更好的方法是以某种方式组合特性,这样一方面的缺点就可以由另一种技术弥补(反之亦然)。优点和缺点的结合。这就是SAP HANA的秘密。不只是内存中的能力,不列存储,不压缩;而是这两者的巧妙结合。在内存空间中,没有其他数据库供应商能够达到这种程度,主要是出于历史原因。
为什么?享受这2分钟的视频。当然,用我们今天的知识回顾过去是不公平的,但是这个视频仍然很有趣。
主要的论点是你不能把所有的事情都记在脑子里,这是不可能的。如果我们把这句话视为理所当然,那么压缩可能是一条出路。假设1TB的RAM服务器太贵,如果数据可以压缩10倍,那么RAM需求将下降到更便宜的128GB RAM计算机。压缩有缺点,有什么技术可以绕过它?
SAP HANA使用四种技术来实现全利无弊的组合:
-Memory
Columnar Storage
Compression
Insert-Only
每种技术的优缺点
内存
基本思想是内存比磁盘快得多。实际上,这种差别比人们通常看到的要大得多。现代CPU的内存带宽为20g字节/秒或更高,单个磁盘的ssd带宽约为550MByte/秒,硬盘驱动器的带宽约为180MByte/秒,两者相差36和110倍。如果一个程序频繁地使用相同的内存,它会被缓存在CPU的L1或L2缓存中,从而将内存带宽提高10倍。相反,180MB/秒的磁盘速度仅适用于顺序读访问,随机访问对磁盘系统的性能要差得多,而对RAM没有负面影响,对SDDs影响很小。
内存的缺点是内存芯片本身的成本(截至2017年,RAM的成本为7美元/GByte,而磁盘的成本为0.05美元/GByte)和硬件平台需要的成本,以便处理尽可能多的内存。
从绝对数字上看,1TB的内存将是7000美元——可以负担得起。
那么内存计算的优点和缺点是什么呢?
优点:
- 更新数据快
- 插入数据很快
- 阅读是快速
缺点:
- 当电力耗尽时,所有的数据也随之耗尽
- 128GB的服务器便宜,1TB的服务器便宜,64TB的服务器贵,1000TB的服务器根本不存在(比如这里)
压缩
压缩的思想很简单:单个CPU比磁盘快得多,因此压缩数据以减少数据量是有益的,只要它的开销不是太大。因此,每个主要的数据库都支持压缩。但它不是很流行,因为压缩数据库块和解压缩它需要付出代价。最明显的成本开销是在数据库块内更新数据时。必须解压数据库块,将更改的数据合并到其中,然后必须再次压缩该块。
优点:
- 减少所需的大小
缺点:
- 插入需要更多的CPU能力
- 读需要更多的CPU能力
- 更新需要更多的CPU能力
列存储
对于一个简单的select sum(收益),柱状存储是完美的。只有一列是只读的,这只是整个表的一部分。这将比所有表数据都在一个文件中的传统行定向表快得多。
如果选择一整行,则行定向存储听起来更合适。插入新行—相同的参数。
优点:
- 同一列的所有数据都是紧密相连的
缺点:
- 同一行的所有数据都存储在不同的地方
只插入
真正的数据库应该具有这样的一致性:“当触发select语句时,此时提交的所有数据都是可见的,而且只有这些数据”。如果另一个事务确实更改了尚未读取的行,那么它仍然应该在查询执行开始时返回有效的版本。所以旧的值必须保留在某个地方。
从一开始,我所知道的唯一支持这一功能的主流数据库是Oracle (SQL Server可以选择打开/关闭这一功能),但是您必须为这种一致性付出代价。每当Oracle数据库写入器用新数据覆盖一个块时,旧版本就会被复制到数据库的回滚段中。因此,一个简单的更新或插入到现有块需要两个操作,实际的更改加上保留旧的版本。
如果只使用insert,情况就完全不同了。在每个表中,旧数据不会被覆盖,只会被追加。更新现有行意味着使用时间戳作为版本信息附加新行。select语句根据查询执行时间戳选择最新的版本。
优点:
- 写的快
缺点:
- 读起来更慢
- 需要更多的存储空间
结合技术
好吧,所以单独来说,所有的技术都是好主意,其他的供应商也尝试过这些,并且已经建立了适当的利基产品,主要围绕分析用例。一个数据库是纯内存数据库,它需要一个常规数据库来持久存储数据—一个缓存系统,其他数据库可以插入数据,但不能更新或删除。许多支持压缩,但客户通常不支持压缩。
SAP HANA的目标是成为一个真正的RDBMS数据库,它支持分析和事务用例,并且在所有方面都优于其他数据库。所以以上这些缺点都是不可接受的。这是通过结合SAP HANA的四项技术实现的……
首先,我想展示两种技术的结合如何对彼此产生积极的影响。
压缩与列式存储的组合
当出现重复模式时,压缩数据的效果最好。这是一个真实的例子,材料主表(SAP ERP中的MARA)。
MANDTMATNRERSDAVPSTALVORMMTARTMBRSHMATKL80000000000000000002323.01.2004KfalseROH1 80000000000000000003804.09.1995KDEVGtrueHALBM0010780000000000000000004323.01.2004KBVfalseHAWA1 80000000000000000005805.01.1996KLBXfalseHIBEM 80000000000000000005905.01.1996KLBXfalseHIBEM 80000000000000000006812.01.1996KEDPLQXZfalseFHMIA01380000000000000000007810.06.1996KVXtrueDIENM
什么可以更好地压缩整个文件,一行还是一列?
答案是显而易见的,但是,尽管如此,我还是从MARA表中导出了这些列(我的系统的全部20,000行)到一个CSV文件中(1 ' 033KB大),并将包含所有9列的一个文件压缩了。为了进行比较,还创建了9个文件和一个列。
显然,主键不能被压缩太多,它是整个文件大小的一半。其他所有的列都压缩得很好。MANDT文件甚至只有303字节大,ERSDA文件与许多创建日期是12 ' 803字节大。原因很明显,一列中的数据看起来很相似,可以很好地压缩,因此,一行中的数据本质上是不同的,可以压缩得不那么有效。
但这并不是一个公平的比较,因为zip算法倾向于更大的数据集,因为它可以更容易地查找模式,而且它是一个相当积极的算法。在数据库中,目标是降低压缩比,从而减少CPU周期。但是,虽然zip支持单个文件,但是在本例中,9个单独的文件加起来是104KB,但是一个文件中的相同数据是111KB。如果数据量更大,节省的数据量将进一步增长。
优点:
- 压缩列存储比压缩行存储更有效
缺点:
- 压缩需要CPU能力
- 需要找到一个比zip更适合的压缩算法
- 读取、插入和更新整个行仍然没有解决
压缩与插入
压缩有一个重要的缺点,如果一行被更新或删除怎么办?压缩跨越多个行,因此当更新单个值时,必须重新解压、修改和压缩整个单元。使用传统数据库并打开压缩,这正是在磁盘块级别上发生的事情。
那么SAP HANA是做什么的呢?它不更新和删除现有的数据!
相反,它将更改作为一个新版本附加一个时间戳作为版本信息,当表被查询时,它将返回每一行的最老版本,即与查询执行开始时间匹配的最老版本。因此不需要重新压缩,数据被追加到表的末尾,而未压缩的区域一旦超过限制,它就会被一次性压缩。
这种方法的另一个优点是,如果单个行被多次更新,那么将更新哪一行?十年前订的?不太可能。它将是一个最近的,一个仍然是在未压缩的地区?
优点:
- 更新和删除不会影响压缩数据
- 压缩是成批完成的,而不是单独的行,这使它更有效率
- 未压缩区域中同一行的更新会增加此空间,但在压缩时,只获取最新的版本
- 因此,只执行插入的方法不会使表增长太多
缺点:
- 压缩需要CPU能力
- 更新压缩区域中的行会导致表仍然增长
- 为每个表提供未压缩和压缩的区域是有权衡的
柱状存储与纯插入(+内存)
由于数据只插入到最后,所以每个操作在表中都有唯一的行号。最初表是空的,然后插入第一行,即第1行。下一行是#2。第一行的更新意味着添加行号为#3的新行。
反对使用列存储的主要理由是,由于现在需要读取多个列,因此读取整个行的成本更高。但这是真的吗?
在这个例子中什么更快?
Column AColumn BColumn CRow 1KathrynBigelowfemaleRow 2QuentinTarantinomaleRow 3FritzLangmale
读取细胞(3,A) + (3,B) + (3,C)还是读取细胞(A,3) + (B,3) + (C,3)?这么说吧,答案显然是两者都不是。没关系。
那么“行定位更适合读取整行”的假设是从哪里来的呢?因为数据非常接近。如果数据存储在磁盘上,这是一个有效的点。读取文件中的一行意味着将磁盘头定位在该位置,然后立即读取整行。这比阅读每行一列的三行要有效得多。即使对于ssd也是如此,因为那里的数据是按4k页面组织的。最重要的是,磁盘I/O在内部使用512字节块。它们都倾向于水平存储而不是垂直存储。
对于不适用的内存访问。微处理器向DRAM发送一个地址并获取该地址下的数据。如果下一次读取就在附近,或者一个完全不同的地址(几乎)是不相关的。当且仅当地址本身的计算是直接向前的。
这里纯插入帮助细胞容易计算的地址——列和访问第三个值,然后列B和价值立场三个最后列c内存访问是一样的访问,然后列第一,第二和第三的价值。
这没有区别。没有。行式阅读的整个观点都是基于水平阅读比垂直阅读更快的假设。如果数据以水平方式存储在磁盘上,则是正确的。然后将一行的数据紧密地放在一起,这样就可以从磁盘圆筒中一次性读取数据。但对于凭记忆阅读来说,这一点都不重要。
优点:
- 从几个列中读取所有行非常快
- 读取一行的所有列也很快
- 事实上,每个操作都很快
缺点:
- 仅插入会导致表增长
- 如果值的长度不同,如何计算内存地址?
压缩与内存
这很简单。由于压缩,需要的内存更少。因此,更大的数据库可以适合更小的服务器。
另一个方面是压缩的类型。上面已经展示了压缩的几个方面。压缩必须是有效的,但只需要消耗很少的额外CPU开销。压缩必须支持容易计算的内存地址给定行号。
字典压缩作为一种压缩类型怎么样?一个区域存储列数据中实际出现的所有惟一值,并为这个列表建立索引。对于MARA表的MTART列,它将是(1,ROH), (2, HALB), (3, HAWA), (4, HIBE), (5, FHMI), (6, DIEN),……
MANDTMATNRERSDAVPSTALVORMMTARTMBRSHMATKL80000000000000000002323.01.2004KfalseROH1 80000000000000000003804.09.1995KDEVGtrueHALBM0010780000000000000000004323.01.2004KBVfalseHAWA1 80000000000000000005805.01.1996KLBXfalseHIBEM 80000000000000000005905.01.1996KLBXfalseHIBEM 80000000000000000006812.01.1996KEDPLQXZfalseFHMIA01380000000000000000007810.06.1996KVXtrueDIENM
现在实际的列只能存储索引。这里存储的不是每个字符4个的20,000行,而是一个字节的索引号(希望如此)。对于有更长的字符串、值的均匀分布和少数不同的值的情况,这是完全合理的。
如果这些值是集群的,那么这个压缩可以得到增强,就像MANDT是一个完美的候选,它到处都有值800。所以需要存储的是“第一行的值是800,接下来的2万行也是800”。
另一种方法是为每个不同的值设置一个位图。
ROH: 1000000
HALB: 0100000
HAWA: 0010000
HIBE: 0001100
FHMI: 0000010
DIEN: 0000001
所有这些字符串都可以非常有效地压缩,因为它们包含了很多0。在最简单的情况下,这样的压缩将是ROH=1*1,然后是6*0。使用这种方法计算给定行的地址偏移量是非常有效的CPU操作:以及字节操作。此外,过滤记录甚至更有效,而且不需要显式索引!选择*从玛拉MTART = ' ROH ' ?获取ROH的位图,并按照位图中1的位置读取带有数字的行。所以表中的第一行是唯一的结果。
Hana实现了各种不同的压缩方法,以选择最适合每个列的压缩方法。对于主键,对于自由形式的字符串列,对于具有很少不同值的列,对于只有一点不同的列,……所有这些都适合压缩算法。
是的,实现起来可能更复杂,但是这些算法是针对cpu最擅长的方面进行调整的。
优点:
- 需要更少的内存
- 快速压缩和解压缩
- 快速扫描,快到除了主键之外不需要单独的索引
缺点:
- 压缩仍然需要一些CPU能力
- 提交的数据仍然需要以某种方式持久化到磁盘上,否则在服务器关闭时所有数据都将消失
把这四个放在一起
当将这四种技术结合在一起时,几乎所有的缺点都被消除了。
- 压缩:从一种开销变为读写数据的有效方式
- 列存储:它的实现方式对于所有查询的组合都是最优的,少列——多行,多列——单行,任何东西
- 只插入:在最严格的版本中支持读一致性的直接方法,而不需要像乐观锁定这样的侧假设
- 内存:即使大型数据库也能装入内存
但是,仍然存在三个问题:
- 为了不丢失任何提交的数据,需要将数据保存在磁盘上
- 将压缩的行版本与未压缩的版本合并,以限制表的增长
- 数据库太大时的硬件成本
解决点1)是一种常见的技术:每个更改都存储在磁盘上的事务日志文件中。所有数据库都这样做,这是有意义的。如果出现电源故障,并且在提交时将数据持久化到磁盘,则什么也不会发生。重启之后,所有提交的事务都可以从那里读取,内存结构可以重新构建。性能也不是问题,因为磁盘是以非常快的顺序方式写入的——包括硬盘和ssd。
当然,我们不想将事务日志存储永远和重建时间点上的数据库安装,因此压缩的表存储区域一次磁盘作为起点和事务日志需要从那个时候开始的。如果表的压缩区域甚至没有变化(对于许多表来说,这是一个合理的假设),那么它就不需要再次转储到磁盘上。例如按年份划分的财务表。不太可能有人会改变前几年的争吵。或者所有那些永远不会改变的小型帮助表,浮现在我的脑海中……
仅插入(2)仅根据此处提供的信息部分解决。在我们所说的压缩期间,未压缩区域确实会将所有版本折叠成最新的版本,但这并不会阻止在压缩区域中出现同一行的多个版本。考虑到压缩算法的工作方式,没有什么可以阻止我们偶尔合并这些行。是的,这要多做一些工作,但仍然比每次插入/更新/删除时解压缩和重新压缩整个数据要好。通过选择适当的分区方法,希望不会处理整个表,而只处理最近的分区。
很明显,这种批处理正在付出代价。这确实是不可避免的。结果,管理员将看到很多CPU大部分时间处于空闲状态,并且周期性地使用更多的CPU资源——每当大型表的增量合并开始时。
剩下的问题是当数据库太大时该怎么办……
扩展和动态分层
对于大型数据库,一种解决方法是询问“您的ERP或数据仓库数据库有多大?”“真的有那么多客户的数据库,假设10的压缩系数是真实的,我们假设4TB的内存是负担得起的,50%的内存储备是合理的,大于20TB吗?”我得承认,这是个站不住脚的论点。
然后,有一些方法可以突破这个极限
- 向外扩展:不是使用一个大型服务器,而是使用两个较小的服务器。这可以降低成本,但不会永远扩大规模。它让我们超过了数据库大小的两倍,数据库大小的三倍。
- 动态分层:将热数据保存在内存中,热数据存储在磁盘上。从Hana数据库用户的角度来看,所有这些看起来仍然像一个表。惟一的区别是,查询暖数据是在磁盘数据库性能上运行的,而不是在Hana性能上。可能是降低大型数据库成本的另一种选择。
- 两者的结合。
如果数据量更大,我就会问自己,这是否是数据库用例,而不是大数据场景。数据库保证像事务保证、严格的读一致性、并发性……都是必需的吗?如果有疑问,请阅读本文以获取更多信息。在这种情况下,利用大数据技术的数据湖用来存储原始数据,具有集群处理的优点和缺点,而Hana则是包含有趣事实的数据库。这提供了大量数据的廉价存储和处理,以及SAP HANA的响应时间和连接性能。使用诸如智能数据访问之类的SAP HANA选项可以用来隐藏差异。
其他常见的误解
运行所有数据库块都缓存在RAM中的经典数据库不是内存中的数据库。同意吗?以上的解释说明了这一点。是的,当然从缓存读取数据要比从磁盘快。但是随后,磁盘访问模式(集中于顺序访问,将数据放在一个512字节扇区中)被复制到与内存访问无关的地方。在最好的情况下,这毫无理由地提供了性能优化,而实际上,这些假设确实会消耗额外的性能。
最近的一篇新闻稿也激起了我的兴趣:“……Terracotta DB,新一代分布式内存数据库平台……”数据库具有某些特性,如前面提到的事务保证、锁定和读一致性。把不支持SQL的数据库称为…大胆。是的,SAP HANA是一个RDBMS,具有您所期望的所有特性。
然而,我同意SAP HANA中没有什么新东西的说法。柱状存储并不是为SAP HANA而发明的,事实上我在大约20年前就使用过这种工具。同样的,只有插入,整个大数据世界都是建立在这种技术上的。SAP HANA的独特之处在于将这些技术组合起来形成一个数据库。我希望鼓励每个人检查所有其他数据库供应商的脚注,即使是最知名的,在内存的支持方式方面。你会发现诸如“内存特性的权衡”、“乐观锁定”等语句。
原因很简单,因为您需要将这四种技术以一种巧妙的方式组合在一起,以实现所有的好处。由于这些技术影响数据库工作的核心,因此不能将它们添加到现有数据库中,而是需要从头开始构建数据库。