<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Columnar Storage on Yeqown</title>
    <link>https://www.yeqown.xyz/tags/Columnar-Storage/</link>
    <description>Recent content in Columnar Storage on Yeqown</description>
    <generator>Hugo</generator>
    <language>en-US</language>
    <lastBuildDate>Tue, 31 Mar 2026 14:44:37 +0800</lastBuildDate>
    <atom:link href="https://www.yeqown.xyz/tags/Columnar-Storage/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>列式数据库是怎么炼成的</title>
      <link>https://www.yeqown.xyz/2026/03/31/%E5%88%97%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%98%AF%E6%80%8E%E4%B9%88%E7%82%BC%E6%88%90%E7%9A%84/</link>
      <pubDate>Tue, 31 Mar 2026 14:44:37 +0800</pubDate>
      <guid>https://www.yeqown.xyz/2026/03/31/%E5%88%97%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%98%AF%E6%80%8E%E4%B9%88%E7%82%BC%E6%88%90%E7%9A%84/</guid>
      <description>&lt;p&gt;列式数据库与行式数据库最大的区别在于数据的存储方式，也就是它们在磁盘上的组织方式不同。传统的行式数据库常用于 &lt;code&gt;OLTP (Online Transaction Processing)&lt;/code&gt; 场景，在这个场景下需要频繁的进行数据的插入、更新、删除操作，操作的对象往往是单行数据。而列式数据库常用于 &lt;code&gt;OLAP (Online Analytical Processing)&lt;/code&gt; 场景，对于数据的聚合查询更为常见，往往需要扫描某一列的大量数据进行计算。&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;  &lt;img src=&#34;https://www.yeqown.xyz/images/columnar-database/storage-difference.png&#34; alt=&#34;Storage Difference&#34;&gt;&#xA;  &lt;figcaption&gt;Storage Difference&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;如果同时用过两种类型的数据库，就会发现：&lt;/p&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;这里列举的优化原则只是冰山一角，仅用于说明两种数据库最显眼的差异。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;p&gt;使用行式数据库过程中，最简单常见的优化原则就是 &lt;strong&gt;尽可能命中索引、降低 B+ 树高度、减少扫描行数&lt;/strong&gt;，如：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;优先对区分度高的列建立索引&lt;/li&gt;&#xA;&lt;li&gt;覆盖索引（索引中包含查询所需的所有列，避免回表）&lt;/li&gt;&#xA;&lt;li&gt;索引下推（在存储引擎层提前过滤不满足条件的数据）&lt;/li&gt;&#xA;&lt;li&gt;最左前缀匹配原则&lt;/li&gt;&#xA;&lt;li&gt;避免使用函数或者隐式类型转换（如：&lt;code&gt;where date(create_time) = &#39;2022-01-01&#39;&lt;/code&gt;），会导致索引失效&lt;/li&gt;&#xA;&lt;li&gt;避免在索引列上使用 &lt;code&gt;!=&lt;/code&gt;、&lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; 等操作符，会导致索引失效&lt;/li&gt;&#xA;&lt;li&gt;避免深度分页&lt;/li&gt;&#xA;&lt;li&gt;分库分表（提出这一优化方向，也是基于单表数据量过大，索引维护的开销会增加，性能也会退化）&lt;/li&gt;&#xA;&lt;li&gt;等等&amp;hellip;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;减少扫描行数这一思路对于列式数据库同样适用（如分区裁剪），但列式数据库还有另一个很重要的优化方向，那就是 &lt;strong&gt;减少列&lt;/strong&gt;，如：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;行存特性（如果是点查询，列数据库 I/O 反而会增加，这一点和行式数据库正好相悖）&lt;/li&gt;&#xA;&lt;li&gt;只读取查询涉及的列（行存也提倡避免 SELECT *，但由于行存以行为单位读取磁盘，主要减少的是网络传输量而非磁盘 I/O；而列存中每列独立存储，少读一列就直接少一份磁盘 I/O）&lt;/li&gt;&#xA;&lt;li&gt;等等&amp;hellip;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;当然，任何数据库的优化，都逃不开 &lt;strong&gt;减少 I/O&lt;/strong&gt; 这一核心目的。说得更白话一点，如果有一种完美的存储介质，它没有I/O延迟，也不会丢失数据，那么这些优化也就不再需要了。&lt;/p&gt;&#xA;&lt;!-- more --&gt;&#xA;&lt;h2 id=&#34;1-clickhouse-的设计&#34;&gt;1. ClickHouse 的设计&lt;a class=&#34;anchor&#34; href=&#34;#1-clickhouse-%e7%9a%84%e8%ae%be%e8%ae%a1&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;11-整体组件&#34;&gt;1.1 整体组件&lt;a class=&#34;anchor&#34; href=&#34;#11-%e6%95%b4%e4%bd%93%e7%bb%84%e4%bb%b6&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;从 ClickHouse 的架构图来看，列式数据库包含以下核心组件：&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;    &lt;img src=&#34;https://www.yeqown.xyz/images/columnar-database/clickhouse-architecture.png&#34; alt=&#34;ClickHouse Architecture&#34;&gt;&#xA;    &lt;figcaption&gt;ClickHouse Architecture&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;&lt;strong&gt;查询处理层&lt;/strong&gt;&lt;/em&gt;： 查询处理遵循传统范式：解析入站查询、构建并优化逻辑与物理查询计划，然后执行&#xA;&lt;ul&gt;&#xA;&lt;li&gt;SQL Parser&lt;/li&gt;&#xA;&lt;li&gt;SQL Planner&lt;/li&gt;&#xA;&lt;li&gt;Physical Plan Builder&lt;/li&gt;&#xA;&lt;li&gt;Plan Executor&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;&lt;strong&gt;存储层&lt;/strong&gt;&lt;/em&gt;：由不同的表引擎组成，这些表引擎封装了表数据的格式和位置&#xA;&lt;ul&gt;&#xA;&lt;li&gt;MergeTree* Family Tables Engines： 代表了 ClickHouse 中的主要持久化格式&lt;/li&gt;&#xA;&lt;li&gt;Special-Purpose Tables Engines：用于加速或分布查询执行的专用表引擎&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Dictionary&lt;/li&gt;&#xA;&lt;li&gt;Memory&lt;/li&gt;&#xA;&lt;li&gt;Distributed (Data Sharding) 处理分布式&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;&lt;strong&gt;集成层&lt;/strong&gt;&lt;/em&gt;：用于与外部系统进行双向数据交换的虚拟表引擎，例如关系型数据库 (如 PostgreSQL、MySQL) 、发布/订阅系统 (如 Kafka、RabbitMQ) ，或键值存储 (如 Redis) 。还可以与数据湖 (如 Iceberg) 或对象存储中的文件 (如 AWS S3、Google GCP) 交互&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Virtual Tables Engines&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;&lt;strong&gt;正交组件&lt;/strong&gt;&lt;/em&gt;：提供辅助功能&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Thread pools&lt;/li&gt;&#xA;&lt;li&gt;Caches&lt;/li&gt;&#xA;&lt;li&gt;RBAC (Role-Based Access Control)&lt;/li&gt;&#xA;&lt;li&gt;Backups&lt;/li&gt;&#xA;&lt;li&gt;Monitoring&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;&lt;strong&gt;访问层&lt;/strong&gt;&lt;/em&gt;：通过不同协议管理用户会话并与应用程序通信&#xA;&lt;ul&gt;&#xA;&lt;li&gt;User Session&lt;/li&gt;&#xA;&lt;li&gt;Wire protocols&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;我们更进一步，丢掉分布式特性、集成和监控，只保留最影响 OLAP 查询性能的核心设计，如下所示：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
