列式数据库的存储原理-列式数据库存储原理
说起列式数据库,你第一反应可能还是那个搭着冰棍吃生的圆柱体一样的东西,对吧?这种数据库在那会儿还叫 Relational,但咱们今天聊的是 Non-relational。别被这个名字劝退,它实际上就是“列导向”的,跟行导向的表最不一样。
你想想,人要是站在宿舍楼门口,要么刚走进超市,那肯定是先问“有哪些人?”要么“有啥东西卖?”而不是先问“哪个房间里有哪位?”这种直觉,正好对应了列式数据库的思维方式。它的数据就像河流里的沙,是直接一列一列往上游流动的,根本不需求像行数据库那样急着先把所有东西打包成一行再拿出来看。
这种设计思路在存层面就体现出来了,你不用去搞特别复杂的反范式化,数据就是躺着存有那儿,一行一个格子,就像Excel 里的 Sheet 一样,每行代表一个实体,每列代表一种属性。 在存原理上,列式数据库最核心的就是“按需列读”。你数据库里存的是成千上万亿的数据,要是每行都存完所有字段,那磁盘上就得塞满整个数据库,读写效率直接崩盘。列式数据库挺智慧,它只在你需求查询某个字段的时候,才把那个列的数据读出来。
比如你想查“这个人的体重是多少”,它直接去内存里要么硬盘上找那一列,做完就扔,不扫一眼其他数据。
这就好比你去超市买东西,你只想看一件商品的价格,不会顺便把整张货架上所有商品的价格都拿出来看一遍。
这种“只读所需,其余全闭”的策略,是它省下的庞大开销。 那在磁盘上具体是如何存的呢?列式数据库的数据一般是以行的形式存有的,但每行内部的数据结构是高度不均的。
不同的列可能是整数、浮点数、字符串,就连是二进制。对于数值型的列(比如身高、体重),它往往是连续的,就像数学上的连续函数,数量级挺大,但离散性挺小(别看这也是为啥数值型没有那么多特殊值),这种连续的数据存起来要占比较多的磁盘空间,速度也相对快一点。而对于大文本要么二进制数据,比如一篇小说要么一个视频文件,要是把它强行塞进整一行,那整行的长度简直会被文本撑爆,这显然是浪费。
故此,列式数据库会把文本数据单独切出来,作为一个大的字符串列存进去,要么用压缩的方式存。
这就造成了磁盘上的“两极分化”:一局部数据是密集连续的数值列,占据大块空间但读写稍快;另一局部是大块的大文本或二进制列,占据空间小,但读写特别慢。 这种存结构的代价就是“行分裂”。为了配合上述的列导向策略,列式数据库对每一行数据都做了处理:行的长度根据内容自动伸缩。一整行数据,可能前 10 个字节是整数,中间 500 个字节是字符串,后 100 个字节是二进制。
这意味着,要是你的表存了 100 万行数据,每行平均 500 字节,那每行长度在 500 到 1000 字节之间浮动。
这在磁盘上意味着啥?意味着你的索引表(那个用来找数据的目录)本身就变得贼复杂,出于索引本身也是一行一行的,每行的长度也是变异的。
要是每行长度都不一样,写索引的时候就得处理大量不同的长度情况,读的时候算法也得频繁根据行数调整。
这害得列式数据库在处理数据量的增长时,索引的效率会随着行数增添而逐步下降。 举个例子,假设你要查一个团队里所有人有没有加入过某个项目。在关系型数据库里,你查完就扔,没别的反应。但在列式数据库里,要是这个项目用字符串存,那它就得读这一列所有项目标名字,然后一个个比对,直到找到匹配的那条。
要是这一列存的是二进制(比如图片),它得先把这一大堆图片读出来,然后一个个像素要么逐行比对,速度会慢下来。
这就是所谓的“扫描”。
要是你只用一行读,那只能查这一行数据,查不到其他行的数据。
这就像你要查“哪位家有猫”,你得把整页纸翻那会儿,要么把整本书翻出来看。列式数据库的优势就在于它赞成“查询所有列”要么“查询局部列”的混合操作。你能够一次读“姓名”和“职位”,也能够只读“电话”,就连只读“性别”。
这极大地削减了不必要的传输,提升了随机访问的速度。 为了处理这种大小不一的数据行,列式数据库在排序和分区上也有一套自己的戏法。行数据库是按“行”来排序的,行长度差异大,排序起来就费事,特别是要是数据量特别大,行长度差异特别大,排序算法得反复调整。列式数据库则是按“列”来排序的。
你想查所有人的姓名,那就把所有姓名字段放在一起排序。别看排序速度可能慢一点,但一旦排好了,赶明儿查人的名字就特别快,出于数据在物理上已经按顺序堆成了一个个长条的柱子。
这就好比你在图书馆按书名排书架,别看排书架慢,但赶明儿查某本书特别顺手。 还有一种做法叫“列聚簇”要么“列剪枝”。在写数据的时候,列式数据库会把数据张罗成一个个大的“列”,每个列占据一个或多个数据页。
比如你存一个图片,你就把这张图片的所有像素数据塞进一个列里,这个列可能占几个数据页的空间。读数据的时候,数据库直接从这个存放像素的列里启动读,读到多少页就取多少页。
这样,图片的读写速度直接取决于你硬盘上存放像素的那几页的速度,彻底绕开了要扫描那列里所有像素再排序的费事。
这就像你拿着一本字典,不需求一页一页翻,直接去指定那几页。 自然,这种设计也有它的短处,就是维护成本高。出于每一列的数据在磁盘上分布着,写数据的时候得一条条写,读数据的时候得一条条读。
特别是当你涉及大量的分布式存要么跨节点操作时,协调这些分散在磁盘不同位置的列数据,比协调一个聚拢的行数据要复杂一些。
另外,出于数据在列上分裂,索引的维护也变得更加难以捉摸。
要是你要更新一个人的数据,你得知道这一行所有列的新值,然后一个个去写,这和查数据的过程有点像。 总的来说,列式数据库就像是一个专门处理非结构化数据要么结构化数据不同维度的高效管道。它牺牲了某些顺序操作的便利性,换来了读大规模数据时的极致速度。当你一次性需求读取全表,要么你想频繁地筛选某个特定字段(比如只查价格、只查用户 ID)时,列式数据库展现出的效率是其他类型数据库无法比拟的。它那种“列导向”的哲学,让数据在存上更像是一种流动的河,而不是堆积的砖,这种灵活性正是它能在大数据时代不可替代的缘由。
声明:演示网站所有内容,若无特殊说明或标注,均来源于网络转载,仅供学习交流使用,禁止商用。若本站侵犯了你的权益,可联系本站删除。
