数据库表的列存储是优化分析查询性能的一个重要因素,因为它大大降低了整体磁盘 I/O 需求并减少了需要从磁盘加载的数据量。
以下系列插图描述了列式数据存储如何实现效率,以及在将数据检索到内存时如何转化为效率。
第一个插图显示了数据库表中的记录通常如何按行存储到磁盘块中。

在典型的关系数据库表中,每一行都包含单个记录的字段值。在逐行数据库存储中,数据块按顺序存储构成整行的每个连续列的值。如果块大小小于记录的大小,则整个记录的存储可能会占用多个块。如果块大小大于记录的大小,则整个记录的存储可能会占用不到一个块,从而导致磁盘空间的使用效率低下。在联机事务处理 (OLTP) 应用程序中,大多数事务涉及频繁读取和写入整个记录的所有值,通常一次记录一条记录或少量记录。因此,按行存储最适合 OLTP 数据库。
下图显示了如何使用列式存储,将每列的值按顺序存储到磁盘块中。

使用列存储,每个数据块存储多行的单个列的值。随着记录进入系统,Amazon Redshift 透明地将数据转换为每一列的列式存储。
在这个简化的示例中,使用列式存储,每个数据块保存的列字段值是基于行的存储的三倍。这意味着与按行存储相比,为相同数量的记录读取相同数量的列字段值需要三分之一的 I/O 操作。在实践中,使用列数非常多、行数非常多的表,存储效率会更高。
另一个优点是,由于每个块都保存相同类型的数据,因此块数据可以使用专门为列数据类型选择的压缩方案,从而进一步减少磁盘空间和 I/O。有关基于数据类型的压缩编码的更多信息,请参阅压缩编码。
在磁盘上存储数据所节省的空间也可以用于检索数据并将其存储在内存中。由于许多数据库操作一次只需要访问或操作一个或少量列,因此您可以通过仅检索查询实际需要的列的块来节省内存空间。OLTP 事务通常涉及少量记录的一行中的大部分或所有列,而数据仓库查询通常只读取大量行的少数列。这意味着为相同数量的行读取相同数量的列字段值需要一小部分 I/O 操作,并使用处理逐行块所需的一小部分内存。在实践中,使用具有非常多的列数和非常多的行数的表,效率增益成比例地更大。例如,假设一个表包含 100 列。使用五列的查询只需要读取表中包含的大约百分之五的数据。对于大型数据库,这种节省可能会重复用于数十亿甚至数万亿条记录。相反,按行数据库也会读取包含 95 个不需要的列的块。使用五列的查询只需要读取表中包含的大约百分之五的数据。对于大型数据库,这种节省可能会重复用于数十亿甚至数万亿条记录。相反,按行数据库也会读取包含 95 个不需要的列的块。使用五列的查询只需要读取表中包含的大约百分之五的数据。对于大型数据库,这种节省可能会重复用于数十亿甚至数万亿条记录。相反,按行数据库也会读取包含 95 个不需要的列的块。
典型的数据库块大小范围从 2 KB 到 32 KB。Amazon Redshift 使用 1 MB 的块大小,效率更高,并进一步减少了执行任何数据库加载或属于查询执行一部分的其他操作所需的 I/O 请求数量。
文章来源:https://docs.aws.amazon.com/redshift/latest/dg/c_columnar_storage_disk_mem_mgmnt.html




