原文:[Column-Stores vs. Row-Stores: How Different Are They Really](http://www.cs.umd.edu/~abadi/papers/abadi-sigmod08.pdf) # ABSTRACT 列存不仅仅只是 IO 更高效(分析场景下读操作)。 列存与行存两者在查询执行层面也有着很大的不同,如 vectorized、compression 以及 join 算法等。 结论:**两个层次** storage layer 和 query executor 都必须改变才能完整发挥列存的优势。 -------------------- # 1. INTRODUCTION - 尝试在 row-store 中模拟 column-store 的物理结构: - 垂直切分 table 为多个只有两列(key,attribute)的 tables - 为查询涉及到的所有列建立索引 - 为每个查询需要的列建立物化视图 结果是查询性能仍然很差。 - column-oriented DBMS 专用的优化技术: - Late materialization ( [[12-query-execution-1#Late Materialization | Late Materialization]] ) - Block iteration([[12-query-execution-1#2.3 Vectorization Model | Vectorization Access Model]] ) - 列存专用的压缩技术如 run-length encoding,以及 Late materialization 时直接在压缩数据上操作 - 提出新优化:invisible joins - 对不同的优化项的提升效果分别对比: - compression:一些场景下有**数量级**的提升,但有些场景却提升很小 - late materialization:3 倍性能提升 - 其他:平均 1.5 倍 简单的列存(没有 compression 和 late materialization)**不能**比优化过的行存好太多。 ----- # 2. BACKGROUND AND PRIOR WORK - [MonetDB](https://dl.acm.org/doi/pdf/10.1007/s007780050076) 和 [MonetDB/X100](https://www.cidrdb.org/cidr2005/papers/P19.pdf) :现代列存数据库和向量化执行的先锋 它们证明了列存设计带来了更好的 CPU 和 cache 性能(除了减少 IO),TPC-H 上打败了其他商用和开源的数据库 - fractured mirrors:行列混合 行存处理更新,后台迁移到列存。 - [C-Store](https://web.stanford.edu/class/cs345d-01/rl/cstore.pdf):更新的列存数据库 可以直接在压缩后的数据上进行操作 --------- # 3. STAR SCHEMA BENCHMARK SSBM 是从 TPC-H 衍生而来的数仓 benchmark。 ## Schema 只有一个 fact table - LINE-ORDER 表 合并了 TPC-H 中的 LINEITEM 和 ORDERS 两个表。 17列,主键:( ORDERKEY, LINENUMBER) 通过外键引用其他维表 ------- # 4. ROW-ORIENTED EXECUTION 几种可以用来用行存模拟列存的技术。 - Vertical Partitioning - Index-only plan - Materialized Views -------- # 5. COLUM-ORIENTED EXECUTION ## 5.1 Compression - 按列存储数据,可以达到**更高**的压缩率。 - 压缩能提升性能的关键在于能**节省IO** - 如果可以在**压缩数据上直接进行操作**,则可以进一步提升性能 - 如果列是**排序**过的,则压缩的优势更大(可能出现连续多个values都是相同的) 每个列都排序开销太大,按照多个列组合排序也有较好效果 ## 5.2 Late Materialization - **tuple construction** 列存中,tuple 的数据分布在不同的位置 大多数查询需要访问多个列,就需要在某个时间点组装分散的列,还原为 tuple - **late materialization** operator 之间传递 position lists - **late materialization 的优势** 1. 许多 selection 和 agg 计算,不需要整个 tuple 3. construction 必须**解压**(然后才能跟其他列值合并),失去了直接对压缩数据进行操作的优势 4. cache 性能更好,因为 cache line 不会被其他无关的列污染 5. block iteration 处理固定长度的列值更高效。而 construction 可能引入其他变长的列,导致 tuple 成为变长的。 > 思考:如果内存中组织成列存,某些点的优势可能不再存在 ## 5.3 Block Iteration 在列存下,将同一列的一批 values 在一个函数调用内发生给 operator。 进一步地,如果列是**固定长度**的,values 可以直接通过数组下标迭代,在当代 CPU 下能发挥潜在的并行能力。 ## 5.4 Invisible Join - 适用场景:列存数据库,星型表的外键/主键 join - invisible join 也是一种 late materialized join,但是最小化需要乱序提取的 values - 工作原理: 将 join 重写为在 fact table 的外键列执行 predicates