【StoneDB研发日志】列式存储 delete方案调研

MySQL删除数据的方式

以MySQL 5.7为例,数据库删除数据的方式一共有以下三种:

  1. delete
  2. truncate
  3. drop

三种方式都可以删除数据,但使用场景有所不同。

[En]

Data can be deleted in all three ways, but the usage scenarios are different.

对于删除整个表的速度:

[En]

For the speed at which the entire table is deleted:

drop > truncate >> delete

MySQL删除数据的方式-delete

delete是属于数据库的DML操作语言,一般是根据条件逐行进行删除。
使用delete删除数据时,数据库只能删除数据不能删除表的结构,并且会触发数据库的事务机制。
delete执行时,会先将所删除数据缓存到rollback segment中,事务commit之后生效;
在InnoDB中,使用delete其实并不会真正的把数据删除,是一种逻辑删,数据库底层实际上只是给删除的数据做了一个已删除的标记,因此,删除数据后的表占空间大小和删除前是一样的.

MySQL删除数据的方式-drop

drop属于数据库DDL定义语言,同 truncate ,执行后立即生效,无法找回。
drop table table_name立刻释放磁盘空间 ,drop 语句将删除表的结构、被依赖的约束(constraint)、触发器(trigger)、索引(index); 依赖于该表的存储过程/函数将保留,但是变为 invalid 状态。

删除数据的方式-TianMu 引擎的支持情况

目前StoneDB的TianMu引擎是支持 truncate 语句 和 drop 语句的,但是delete语句目前还不支持。

TianMu引擎需要不需要delete?

TianMu引擎设计的初衷

TianMu是一个列式存储引擎,列式存储的出现主要是为了方便快捷查询和高效存储大量同类型的数据而设计的,主要使用场景就是OLAP场景。下面是OLAP场景的部分关键特征:
①绝大多数是读请求
②数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。
无法修改③已添加到数据库中的数据。

[En]

Data that ③ has added to the database cannot be modified.

对于读取,④从数据库中提取相当数量的行,但只提取一小部分列。

[En]

For reads, ④ extracts a considerable number of rows from the database, but only a small portion of the columns.

⑤列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)
⑥在处理单个查询时需要高吞吐量(每个服务器每秒几十亿行)

[En]

⑥ requires high throughput when processing a single query (billions of rows per server per second)

⑦事务不是必须的
⑧对数据一致性要求低

目前行业现状

支持列存储的数据库类型 是否支持delete 备注

MariaDB ColumnStore 支持 SQL Server 支持 Oracle In-Memory Column Store 支持 DB2 BLU Acceleration 支持 MySQL HeatWave 不支持 主要作为辅助引擎,支持DML同步 TiFlash 不支持 主要作为辅助引擎,支持DML同步 PolarDBIn-Memory Column Index 支持 openGauss 支持 ClickHouse 支持 非标准的DELETE操作

OLAP场景下 对于数据的delete的操作可以说没有或者频率很小,同时列式存储对比行式存储来说并不擅长数据的增删改,如果是为了极致的查询性能,完全可以舍弃 DML 操作。但是为了功能的完整性,提升产品的竞争力,目前我们也放开了 insert 和 单表的 update 的功能,delete功能暂时还不支持,未来我们将对改功能进行支持。

主流列式数据库的delete方案

本节主要讲以下三种列式存储数据库的delete方案:
openGauss
ClickHouse
PolarDB

openGauss 列存储引擎的方案

底层存储结构

openGauss底层存储结构与stonedb类似 ,存储基本单位是CU(Compression Unit,压缩单元),即表中一列的一部分数据组成的压缩数据块。行存引擎中是以行作为单位来管理,而当使用列存储时,整个表整体被按照不同列划分为若干个CU。

【StoneDB研发日志】列式存储 delete方案调研
CU文件本身结构,则如下图所示。
【StoneDB研发日志】列式存储 delete方案调研
每个CU对应一个CU Desc的记录,在CU desc里记录了整个CU的事务时间戳信息、CU的大小、存储位置、magic校验码、min/max等信息。
【StoneDB研发日志】列式存储 delete方案调研
每张列存表还配有一张Delta表,Delta表自身为行存储表。当有少量的数据插入到一张列存表时,数据会被暂时放入Delta表,等到到达阈值或满足一定条件或操作时再行整合为CU文件。Delta表可以避免单点数据操作带来的很重的CU操作与开销。

删除策略

  • 列存储的CU中数据的删除,实际上是标记删除。删除操作,相当于是更新了CUDesc表中CU对应CUDesc记录的delete bitmap(删除位图)结构,标记列中某行对应数据已被删除,而CU文件数据不会被更改。这样可以避免删除操作带来的IO放大以及解压、压缩的高额CPU开销。这样的设计,也可以使得对于同一个CU的select(查询)和delete(删除)互不阻塞,提升并发能力。列存储CU中数据更新,则是遵循append-only(仅允许追加)原则的,即CU文件仅会向后进行延展扩充,亦或是启用新的CU文件,而不是在对应行在CU中的位置就地更新。

【StoneDB研发日志】列式存储 delete方案调研

失效空间的清理

  • 由于CU以及CUDesc的元数据管理模式,原有系统中的Vacuum机制实际上并不会非常有效的清除CU中已经失效的存储空间,因为Lazy Vacuum(清理数据时,只是标识无用行的状态可以录入新数据,不会影响对表数据的操作)仅能在CUDesc级别进行操作,在多数场景下无法对CU文件本身进行清理。列存储内部如果要对列存数据表进行清理,需要执行Vacuum Full(除了清理无用行,还会合并数据块,整个过程会锁定表)操作。

ClickHouse delete 方案

特点:缺乏修改或删除现有数据的高频、低延迟能力。只能用于批量删除或修改数据。

[En]

Features: lack of high-frequency, low-latency ability to modify or delete existing data. Can only be used to bulk delete or modify data.

数据有序存储
ClickHouse支持在建表时,指定将数据按照某些列进行sort by。排序后,保证了相同sort key的数据在磁盘上连续存储,且有序摆放。在进行等值、范围查询时,where条件命中的数据都紧密存储在一个或若干个连续的Block中,而不是分散的存储在任意多个Block, 大幅减少需要IO的block数量。另外,连续IO也能够充分利用操作系统page cache的预取能力,减少page fault。

【StoneDB研发日志】列式存储 delete方案调研

delete 策略

ClickHouse是个分析型数据库。
OLAP场景下,数据一般是不变的,因此ClickHouse对update、delete的支持是比较弱的,实际上并不支持标准的update、delete操作。
ClickHouse通过alter方式实现更新、删除,它把update、delete操作叫做mutation(突变)。
标准SQL的更新、删除操作是同步的,即客户端要等服务端返回执行结果(通常是int值);
而ClickHouse的update、delete是通过异步方式实现的,当执行update语句时,服务端立即返回,但是实际上此时数据还没变,而是排队等着。
Mutation具体过程
首先,使用where条件找到需要修改的分区;然后,重建每个分区,用新的分区替换旧的,分区一旦被替换,就不可回退;对于单独一个分区,是原子性的;但对于整个mutation,如果涉及多个分区,则不是原子性的。

PolarDB In-Memory Column Index

特点:PolarDB将列存实现为InnoDB的二级索引
在PolarDB中所有Primary Index和Secondary Index都实现为一个B+Tree。列索引在定义上是一个Index,但其实是一个虚拟的索引,用于捕获对该索引覆盖列的增删改操作。

【StoneDB研发日志】列式存储 delete方案调研
如上图所示,在PolarDB中所有Primary Index和Secondary Index都实现为一个B+Tree。而列索引在定义上是一个Index,但其实是一个虚拟的索引,用于捕获对该索引覆盖列的增删改操作。
对于上面的表其主表(Primary Index)包含(C1,C2,C3,C4,C5) 5列数据, Seconary Index索引包含(C2,C1) 两列数据, 在普通二级索引中,C2与C1编码成一行保存在B+tree中。而其中的列存索引包含(C2,C3,C4)三列数据. 在实际物理存储时,会对三列进行拆分独立存储,每一列都会按写入顺序转成列存格式。
列存实现为二级索引的另一个好处是执行器的工程实现非常简单,在MySQL中已经存在覆盖索引的概念,即一个查询所需要的列都在一个二级索引中存储,则可以直接利用这个二级索引中的数据满足查询需求,使用二级索引相对于使用Primary Index可以极大减少读取的数据量进而提升查询性能。当一个查询所需要的列都被列索引覆盖时,借助列存的加速作用,可以数十倍甚至数百倍的提升查询性能。

实现为InnoDB二级索引方案的优点:

1.查询执行器的工程实现非常简单
2.可以复用InnoDB的事务处理框架
3.可以复用InnoDB的数据编码格式
4.DDL语句操作非常灵活
5.可以复用InnoDB的Redo事务日志模块
6.二级索引与主表有一样的生命周期,方便管理

列存数据组织

对ColumnIndex中每一列,其存储都使用了无序且追加写的格式,结合标记删除及后台异步compaction实现空间回收。其具体实现上有如下几个关键点:
列索引中记录按RowGroup进行组织,每个RowGroup中不同的列会各自打包形成DataPack。
每个RowGroup都采用追加写,分属每个列的DataPack也是采用追加写模式。对于一个列索引,只有个Active RowGroup负责接受新的写入。当该RowGroup写满之后即冻结,其包含的所有Datapack会转为压缩格保存到磁盘上,同时记录每个数据块的统计信息便于过滤。
列存RowGroup中每新写入一行都会分配一个RowID用作定位,属于一行的所有列都可以用该RowID计算定位,同时系统维护PK到RowID的映射索引,以支持后续的删除和修改操作。
删除操作只需要设置一个删除标志位。

[En]

The delete operation requires only one delete flag bit to be set.

更新操作采用标记删除的方式来支持,对于更新操作,首先根据RowID计算出其原始位置并设置删除标记,然后在ActiveRowGroup中写入新的数据版本。
当一个RowGroup中的无效记录超过一定阈值,则会触发后台异步compaction操作,其作用一方面是回收空间,另一方面可以让有效数据存储更加紧凑,提升分析型查询单的效率。

【StoneDB研发日志】列式存储 delete方案调研

delete 策略

删除操作只需要设置一个删除标志位。

[En]

The delete operation requires only one delete flag bit to be set.

更新操作采用标记删除的方式来支持,对于更新操作,首先根据RowID计算出其原始位置并设置删除标记,然后在ActiveRowGroup中写入新的数据版本。
当一个RowGroup中的无效记录超过一定阈值,则会触发后台异步compaction操作,其作用一方面是回收空间,另一方面可以让有效数据存储更加紧凑,提升分析型查询的效率。

各列式存储的delete方案汇总

支持列存储的数据库类型 存储结构 Delete策略

MariaDB ColumnStore 固定大小的数据块+元数据 标记删除 SQL Server 列存储索引+行组+列段 标记删除 PolarDB In-Memory Column Index 列存储索引+RowGroup+DataPack+元数据 标记删除 openGauss 元数据+数据包 标记删除 ClickHouse 有序存储+分区数据包 新建分区替换

TianMu引擎 delete 功能规划

GitHub issue 链接:
https://github.com/stoneatom/stonedb/issues/343

【StoneDB研发日志】列式存储 delete方案调研

TianMu引擎 delete 功能实现流程图

【StoneDB研发日志】列式存储 delete方案调研

Original: https://www.cnblogs.com/yangwilly/p/16591997.html
Author: 来来士
Title: 【StoneDB研发日志】列式存储 delete方案调研

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/505016/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • centos下安装jdk8和maven

    创建目录 mkdir -p/usr/local/java/ 网盘拉去JDK和Maven 链接:https://pan.baidu.com/s/1GgJk8ji0r-tjGAj_ea…

    数据库 2023年6月6日
    076
  • 绕过国内域名备案

    情景:现有域名jsw.top,云服务器1台均在阿里云下。域名jsw.top、www.jsw.top CNAME解析到阿里云OSS的记录值(阿里云OSS会要求备案,导致无法使用),而…

    数据库 2023年6月14日
    092
  • 2022-8-27 vue 第一天

    什么是vue? Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建…

    数据库 2023年6月14日
    075
  • MySQL函数学习(五)—–流程控制函数

    md函数笔记五 注:笔记旨在记录 五、MySQL 流程控制函数 0. 表 0.1 num表: 1. IF() — 条件判断 1.1. 函数: 1.2. sql示例: 2…

    数据库 2023年5月24日
    085
  • html简单学习!

    博主学习html的随记 1.常用标签 1.基础标签 2.格式标签 3.表单 4.超文本标签 5.列表 6.表格 7.样式 8.特殊符号 9.内联框架(网页嵌套) 1.常用标签 1….

    数据库 2023年6月16日
    0100
  • centos下安装myrocksdb

    承接上一篇,https://www.cnblogs.com/lunyu/p/10190364.html 。编译安装myrocks的整个过程,特别是第2步和第7步,让人冗长难耐。因此…

    数据库 2023年6月14日
    0115
  • [spring]spring中java实现类代替注解开发

    9.使用javaconfig实现代替xml配置 The central artifacts in Spring’s new Java-configuration sup…

    数据库 2023年6月16日
    078
  • MySQL–SELECT检索语句

    1、检索单个列 SELECT prod_name FROM products; –上述语句利用 SELECT语句从 products表中检索一个名为prod_name的列。 Vi…

    数据库 2023年6月16日
    094
  • 一句话的需求怎么测?需求文档的三种现状及应对策略

    转载请注明出处❤️ 你好,我是测试蔡坨坨。 今天,我们来聊聊需求文档那些事儿…… 众所周知,软件需求是软件项目研发的开始,是组建研发团队后第一次集体讨论的事…

    数据库 2023年6月11日
    087
  • 即时通讯课设Android端问题记录

    转眼间,就已经是大四学生,目前正在写毕设。Android 端没有系统的学习过,都是哪里不会查哪里,基本靠度娘。所以,在此记录下课设开发过程中,Android 端遇到的问题。 在主线…

    数据库 2023年6月9日
    058
  • 你是否听说过 HashMap 在多线程环境下操作可能会导致程序死循环?

    作者:炸鸡可乐原文出处:www.pzblog.cn 一、问题描述 经常有些面试官会问, 是否了解过 HashMap 在多线程环境下使用时可能会发生死循环,导致服务器 cpu 100…

    数据库 2023年6月14日
    080
  • list对象中的数据如何去重呢?

    下文笔者讲述list对象的去重方法分享,list的实现类是我们存储数据的容器, 当里面存储的对象存在重复值时,我们该如何对其进行去重操作呢? 下文笔者将一一道来,首先我们需了解对象…

    数据库 2023年6月11日
    094
  • Tomcat总体架构(二)

    目录 八、PipeLine 和 Valve 九、Connector 十、Executor 十一、Bootstrap 和 Catalina 十二、组件总结 N、结束 视频 八、Pip…

    数据库 2023年6月11日
    0110
  • MyBatis详解

    😀搭建 MyBatis mysql mysql-connector-java 8.0.29 org.mybatis mybatis 3.5.7 junit junit 4.12 t…

    数据库 2023年6月14日
    082
  • InnoDB 中不同SQL语句设置的锁

    锁定读、UPDATE 或 DELETE 通常会给在SQL语句处理过程扫描到的每个索引记录上设置记录锁。语句中是否存在排除该行的WHERE条件并不重要。InnoDB不记得确切的WHE…

    数据库 2023年6月14日
    0109
  • 优秀体现在细微处

    上面是团队内小王同学整理的需求评审计划,我们看最后一列的细节之处,即,加上了与这个需求相关的资料。 希望我们都能像上面的小王同学一样。 我们的信息,从不同角度来看,总会分散在不同的…

    数据库 2023年6月9日
    093
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球