1. 什么是列式存储?
在说列式存储之前,先来说一下传统的行式存储。传统的行式存储以行为单位储存数据,每条记录会被存为一个完整的行,无论这个记录是否有完全的数据,这些数据都会被存储,这样就会造成存储空间的浪费。而列式存储则是将数据存储在列上,将一列完整的数据做为最小单位,具有很好的压缩率和查询性能。通常情况下,我们需要查询的数据并不是所有的列,这时候,列式存储可以只读取需要查询的数据列,这样就大大减少了数据读取的开销,可以提高数据查询的速度。
下面,我们将分别从存储优势和查询优势两个方面来详细介绍列式存储。
2. 列式存储的存储优势
2.1 空间利用率
以行式存储来描述一个表的情况,每一行都是记录的一个完整集合,而这一行中包括了所有的属性字段,但是在实际使用过程中,每一行数据原本应该是由很多个属性字段组成的,这个组成可以根据不同的需求来决定,而在一些情况下,某些属性字段可能会很少被用到,这个时候,对于行式存储来说就会浪费大量的空间,这个可能会严重影响存储设备效果。而列式存储大大优化了这个问题,底层数据结构与行式存储数据结构相反,将属性字段做成了列,每一列的数据是相同类型的,这样会极大地提高空间利用率。
2.2 数据压缩
由于每个属性在一般情况下都有较多的重复数据,而使用列式存储时,我们可以针对每一列进行单独的压缩,这样就会大大减少存储空间,这样大大提升了存储空间的利用率。
CREATE TABLE users (
id INT,
name VARCHAR(255),
age INT,
score FLOAT
);
INSERT INTO users VALUES
(1, 'Alice', 20, 70.5),
(2, 'Bob', 23, 80.0),
(3, 'Charlie', 22, 77.8),
(4, 'David', 21, 89.2);
如上所述,我们在使用行式存储时,每行都包含了所有属性字段,比如第一行记录:(1,'Alice',20,70.5);而在列式存储中,由于我们将属性字段作为列,例如id、age、score就可以分成3组数据,即id:[1,2,3,4]、age:[20,23,22,21]、score:[70.5,80.0,77.8,89.2],再对每组单独进行压缩,例如,对于score列我们可以进行浮点数压缩,由于数据集中在70分以上,因此可以选用浮点压缩而不会对数据产生太大影响,最终得到的压缩结果可能是这样的:
id: 1 2 3 4
age: 20 23 22 21
score:f3,f4,f3,f5
3. 列式存储的查询优势
3.1 查询速度
在处理查询时,列式存储具有很好的性能优势。因为所有类型相同列的数据在磁盘上是连续存储的,所以在读取和解压数据时会非常迅速。并且,由于查询往往只需要击中数量很少的行中的少数列,因此列式存储减少了不必要数据的IO与CPU计算操作,提高了查询效率。
3.2 聚合查询
聚合查询是数据库常见的查询操作之一,如对某个字段求和、计数或者找出最大值,平均值等等,对于行式存储来说,需要扫描所有的行才能完成聚合操作,而列式存储将数据进行切分后,则只需要扫描一部分列,这个操作就会变得非常快速。
4. SQL Server列式存储使用
SQL Server 2016引入了列式存储引擎,以提供行式存储和列式存储之间的灵活性。使用列式存储引擎时,可以在一张用户表中包含行式存储和列式存储的两种格式,而用户可以根据实际情况来选择不同的格式。
下面简单演示如何在SQL Server中创建列存储表。
--创建内存列式存储表
CREATE TABLE StockMemory (
StockDate datetime2(0),
stockSymbol nvarchar(20),
Volume float NULL,
Price float NULL,
OpenPrice float NULL,
LowPrice float NULL,
HighPrice float NULL
) WITH (
MEMORY_OPTIMIZED = ON,
DURABILITY = SCHEMA_ONLY
)
--创建磁盘持久化列式存储表
CREATE TABLE StockDiskPersisted(
StockDate datetime2(0) ,
stockSymbol nvarchar(20) ,
Volume float NULL,
Price float NULL,
OpenPrice float NULL,
LowPrice float NULL,
HighPrice float NULL
) WITH (
DISTRIBUTION = HASH(stockSymbol),
CLUSTERED COLUMNSTORE INDEX
);
以上代码创建了两个表,名为StockMemory和StockDiskPersisted,StockMemory为内存列式存储表,而StockDiskPersisted则是磁盘持久化列式存储表。在创建表时,通过添加WITH (MEMORY_OPTIMIZED = ON)选项,将在内存中创建存储表,而在创建磁盘持久化列式存储表时,要添加特定选项,如上述代码示例中的CLUSTERED COLUMNSTORE INDEX。
5. 总结
列式存储是一种以列为单位存储数据的数据库技术,相对于传统的行式存储,它可以提供更高的存储空间、更好的数据压缩、更快的数据查询等优势。SqlServer列式存储提供了行式存储和列式存储之间的灵活性,在创建存储表时,可以根据实际情况选择不同的格式。