MySQL删除数据的形式

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

  1. delete
  2. truncate
  3. drop

以上三种形式都能够删除数据,然而应用场景是不同的。
对于整个表进行删除的执行速度来说:
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行)更新,而不是单行更新;或者基本没有更新。
③已增加到数据库的数据不能批改。
④对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
⑤列中的数据绝对较小:数字和短字符串(例如,每个URL 60个字节)
⑥解决单个查问时须要高吞吐量(每台服务器每秒可达数十亿行)
⑦事务不是必须的
⑧对数据一致性要求低

目前行业现状

反对列存储的数据库类型是否反对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。

CU文件自身构造,则如下图所示。

每个CU对应一个CU Desc的记录,在CU desc里记录了整个CU的事务工夫戳信息、CU的大小、存储地位、magic校验码、min/max等信息。

每张列存表还配有一张Delta表,Delta表本身为行存储表。当有大量的数据插入到一张列存表时,数据会被临时放入Delta表,等到达到阈值或满足肯定条件或操作时再行整合为CU文件。Delta表能够防止单点数据操作带来的很重的CU操作与开销。

删除策略

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

生效空间的清理

  • 因为CU以及CUDesc的元数据管理模式,原有零碎中的Vacuum机制实际上并不会十分无效的革除CU中曾经生效的存储空间,因为Lazy Vacuum(清理数据时,只是标识无用行的状态能够录入新数据,不会影响对表数据的操作)仅能在CUDesc级别进行操作,在少数场景下无奈对CU文件自身进行清理。列存储外部如果要对列存数据表进行清理,须要执行Vacuum Full(除了清理无用行,还会合并数据块,整个过程会锁定表)操作。

    ClickHouse delete 计划

    特点:短少高频率,低提早的批改或删除已存在数据的能力。仅能用于批量删除或批改数据。
    数据有序存储
    ClickHouse反对在建表时,指定将数据依照某些列进行sort by。排序后,保障了雷同sort key的数据在磁盘上间断存储,且有序摆放。在进行等值、范畴查问时,where条件命中的数据都严密存储在一个或若干个间断的Block中,而不是扩散的存储在任意多个Block, 大幅缩小须要IO的block数量。另外,间断IO也可能充分利用操作系统page cache的预取能力,缩小page fault。

    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,但其实是一个虚构的索引,用于捕捉对该索引笼罩列的增删改操作。

    如上图所示,在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的映射索引,以反对后续的删除和批改操作。
    删除操作只须要设置一个删除标记位。
    更新操作采纳标记删除的形式来反对,对于更新操作,首先依据RowID计算出其原始地位并设置删除标记,而后在ActiveRowGroup中写入新的数据版本。
    当一个RowGroup中的有效记录超过肯定阈值,则会触发后盾异步compaction操作,其作用一方面是回收空间,另一方面能够让无效数据存储更加紧凑,晋升剖析型查问单的效率。

    delete 策略

    删除操作只须要设置一个删除标记位。
    更新操作采纳标记删除的形式来反对,对于更新操作,首先依据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

TianMu引擎 delete 性能实现流程图