DolphinDB内存表详解

本文给出文章信息(作者与发布日期),并围绕 DolphinDB 内存表的重要性与本文覆盖范围展开说明。

Source: https://dolphindb.cn/blogs/77

What this page covers

技能认证特训营第二期报名活动

页面顶部提供活动推广与报名链接入口。

DolphinDB内存表详解(文章信息与导语)

文章给出标题、作者与日期,并说明内存表的重要性与本文覆盖范围。

内存表类别总览

按使用场景与功能特点,将 DolphinDB 内存表划分为四类。

常规内存表:创建与应用

介绍常规内存表的能力、table 函数创建方式、容量扩展机制与使用注意事项。

键值内存表:创建、写入更新语义与应用场景

说明键值内存表的主键约束、keyedTable 创建方式、插入触发更新行为与典型应用场景。

流数据表:创建、操作限制、持久化机制与应用场景

描述流数据表的发布/订阅含义、创建与转换、更新/删除限制,以及通过持久化保留历史数据的机制。

MVCC内存表:隔离模型、实现限制、创建与持久化、应用场景

解释 MVCC 内存表的多版本并发与快照隔离、当前实现的锁粒度限制,以及创建、持久化与适用场景。

共享内存表:共享方式与删除

内存表默认仅在创建会话可见;可用 share 共享,并可用 undef 删除共享表。

共享内存表:对所有会话可见

示例展示共享后,其他会话可通过共享变量访问并修改同一内存表数据。

共享内存表:线程安全与并发读写模型差异

对比不同内存表在共享时的并发控制与锁策略,并讨论 copy-on-write 与 OOM 风险。

分区内存表:动机、类型与创建方式

介绍分区内存表通过子表锁提升并发,并给出创建不同分区表的示例与限制。

分区内存表:增加查询并发性与快照隔离权衡

分区可提升查询并发,但在隔离性上存在权衡,并提供并发查询耗时对比与说明。

分区内存表:增加写入并发性与共享保障

展示对不同分区并行写入方式,并指出同分区并发写风险;可通过共享分区表保障一致性。

数据操作比较:增删改查支持

对比四类内存表在 CRUD 支持与查询优化条件上的差异。

数据操作比较:并发性支持

对比四类内存表在共享/分区条件下的并发读写支持差异与限制。

数据操作比较:持久化能力

说明常规/键值不持久化,流表持久化前提与策略,以及 MVCC 表的持久化与重启加载方式。

表结构操作比较(schema变更)

对比四类内存表在共享/分区状态下对列新增、删除、修改与列顺序调整等结构操作支持。

小结

概括 DolphinDB 支持四类内存表,并引入共享与分区以满足内存计算与流计算需求。

Facts Index

Entity Attribute Value Confidence
DolphinDB内存表详解发布日期2021-08-05high
DolphinDB内存表详解作者署名Junxihigh
DolphinDB 内存表重要性描述内存表是DolphinDB数据库的重要组成部分,可用于高速数据读写与缓存计算引擎中间结果以加速计算过程medium
DolphinDB 内存表分类数量与类别四种:常规内存表、键值内存表、流数据表、MVCC内存表high
常规内存表支持的操作支持增删改查等操作high
常规内存表SQL查询结果存储位置SQL查询返回的结果通常存储在常规内存表中high
table 函数创建常规内存表的方式两种:按schema与容量(capacity)/初始行数(size)创建;或通过已有数据(矩阵、表、数组、元组)创建high
常规内存表容量扩展行为记录数超过容量时系统自动扩充;扩充时先分配更大内存(增加20%到100%不等),复制旧表到新表后释放原内存high
常规内存表容量设置建议若可预估行数,建议创建时预先分配合理容量以避免大表扩容成本高medium
常规内存表初始行数为0的结果初始行数为0时系统生成空表high
常规内存表初始行数非0的结果初始行数不为0时系统生成指定行数的表,各列值为默认值high
常规内存表内存不足时行为系统内存不足时不会自动溢出到磁盘,会抛出Out Of Memory异常high
常规内存表使用资源管理建议进行查询/计算时需注意中间与最终结果的size;中间结果不再需要时应及时释放medium
键值内存表定义/能力支持主键(一个或多个字段作为主键唯一确定记录);支持增删改查,但主键值不允许更新high
键值内存表实现与性能原因通过哈希表记录键值到行号映射,因此基于键值的查找和更新效率高high
keyedTable 函数用途用于创建键值内存表;与table类似但增加参数指明键值列名称high
键值内存表容量与初始大小约束指定容量和初始大小创建键值内存表时,初始大小必须为0high
keyedTable 函数转换能力可将常规内存表转换为键值内存表high
键值内存表insert 行为(主键冲突)插入时自动检查主键:主键不存在则新增记录;主键重复则更新该主键对应记录(记录条数不增加)high
键值内存表应用场景单行更新与查询效率高,适合作为数据缓存;并兼容SQL可做更复杂计算(文中与redis对比)medium
键值内存表应用场景可作为时间序列聚合引擎的输出表以实时更新结果(文中引用K线教程)medium
流数据表目的/定义为流数据设计,是流数据发布与订阅的媒介;发布一条消息等价于插入一条记录,订阅等价于将新到达数据推向客户端high
流数据表查询与计算方式对流数据的查询和计算可通过SQL语句完成high
streamTable 函数用途与用法用于创建流数据表;用法与table函数完全相同high
streamTable 函数转换能力可将常规内存表转换为流数据表high
keyedStreamTable用途流数据表支持创建单个键值列可用keyedStreamTable;目的是在高可用(多个发布端同时写入)场景避免重复消息,key通常为消息IDhigh
流数据表不支持的操作不支持更新和删除记录,只支持查询和添加记录high
流数据表持久化机制概述为解决内存有限与流数据连续性,引入持久化:内存保留最新部分数据,更旧数据持久化到磁盘;订阅旧数据时从磁盘读取high
enableTableShareAndPersistence用途(在流表持久化中)用于启用流数据表持久化(文中提示参考流数据教程)medium
流数据表应用场景共享的流数据表用于在流计算中发布数据;订阅端通过subscribeTable函数订阅与消费流数据high
MVCC内存表并发行为存储多个版本数据;多用户同时读写互不阻塞high
MVCC内存表隔离模型数据隔离采用快照隔离模型:用户读取到的是读取前已存在的数据,读取过程中即使数据被修改/删除也不影响正在读的用户high
MVCC内存表(当前实现)写操作锁与实现方式更新和删除时锁定整个表,并使用copy-on-write复制一份数据;因此删除和更新效率不高high
MVCC内存表(未来计划)后续改进方向后续版本将实现行级MVCC内存表medium
mvccTable 函数用途用于创建MVCC内存表high
MVCC内存表持久化方式(创建时指定)创建时可指定持久化目录和表名将数据持久化到磁盘high
loadMvccTable 函数用途系统重启后可将磁盘中的MVCC表数据加载到内存high
mvccTable 函数转换能力可将常规内存表转换为MVCC内存表high
MVCC内存表(当前)适用场景适用于读多写少且有持久化需要的场景(如动态配置系统:改动不频繁,以新增和查询为主)high
共享内存表默认可见性DolphinDB中内存表默认只在创建会话中使用,对其他会话不可见且不支持多用户多会话并发操作high
共享内存表共享方式与覆盖类型四种类型内存表均可共享;使用share命令共享内存表high
undef 函数用途可删除共享表(示例:undef(`st,SHARED))high
共享内存表会话可见性效果共享后其他会话可通过访问共享变量访问内存表,并可插入数据;原会话中原表数据也会随之增加high
共享机制(线程安全)效果与代价共享提供数据安全保护机制,但会影响系统性能medium
常规内存表/流数据表/MVCC内存表(共享时)并发读写模型支持多版本模型,允许多读一写;读写互不阻塞;读不上锁并采用快照隔离;写必须加锁且只允许一个线程修改(添加/删除/更新)high
写操作(共享时)追加写效率添加记录一律在内存表末尾追加,无论内存使用还是CPU使用均非常高效medium
常规内存表与MVCC内存表(共享时)更新/删除实现支持更新和删除,并采用copy-on-write:先复制一份数据形成新版本,再在新版本上删除和修改high
常规内存表与MVCC内存表(共享时)频繁更新/删除风险删除和更新操作内存与CPU消耗较高;当删除更新频繁且读操作耗时导致旧版本不能快速释放时,易导致OOM异常high
键值内存表(共享时)锁策略共享采用不同方法:无论读写都必须加锁;写线程与读线程、多个写线程之间、多个读线程之间均互斥high
键值内存表(共享时)使用建议尽量避免耗时的查询或计算,否则会使其它线程长时间等待medium
分区内存表动机与结构内存表数据量大时可分区;分区后大表由多个子表(tablet)构成,不使用全局锁,锁由每个子表独立管理以提升读写并发能力high
分区内存表支持的分区方式与限制支持值分区、范围分区、哈希分区、列表分区;不支持组合分区high
createPartitionedTable用途用于创建内存分区表high
分区流数据表创建要求创建时需传入多个流数据表作为模板,每个流表对应一个分区;写入时直接写这些流表,查询时查询分区表high
分区MVCC内存表创建要求需传入多个MVCC内存表作为模板,每个表对应一个分区;写入时写这些表,查询时查询分区表high
分区内存表子表动态变更创建后不能再动态增删子表high
分区表查询并发提升三方面原因(1)锁粒度更细提升读并发(特别是键值表查询需加锁);(2)批量计算可并行处理子表;(3)过滤包含分区字段可缩小分区范围避免全表扫描high
并发查询性能对比实验(键值内存表)模拟数据规模500万行数据(n=5000000)high
并发查询性能对比实验(客户端负载)并发与请求次数模拟10个客户端;每个客户端查询10万次,每次查询一条数据high
并发查询耗时(未分区键值内存表)time1(毫秒,10客户端)[6719.266848,7160.349678,7271.465094,7346.452625,7371.821485,7363.87979,7357.024299,7332.747157,7298.920972,7255.876976]high
并发查询耗时(分区键值内存表)time2(毫秒,10客户端)[2382.154581,2456.586709,2560.380315,2577.602019,2599.724927,2611.944367,2590.131679,2587.706832,2564.305815,2498.027042]high
并发查询性能对比结论分区 vs 未分区每个客户端查询分区键值内存表耗时低于查询未分区内存表耗时high
分区内存表查询快照隔离保证查询未分区内存表可保证快照隔离;查询分区内存表不再保证快照隔离,可能读到一部分写入的数据high
分区常规内存表写入并发能力可同时向不同分区写入数据(示例中3个线程写入3个不同分区)high
未共享的分区内存表写入同分区并发写风险需避免同时对相同分区写入;示例说明可能导致系统崩溃并破坏内存high
分区内存表同分区多线程写入的保障方式可将分区内存表共享,以保证每个分区数据安全性和一致性,从而允许多个线程对相同分区写入high
CRUD 支持对比(说明要点)各表类型CRUD支持常规/键值/MVCC内存表支持增删改查;流数据表仅支持增加与查询,不支持删除与更新high
键值内存表查询性能优化条件若过滤条件包含主键,查询性能会明显提升medium
分区内存表查询性能优化条件若过滤条件包含分区列,可缩小要扫描的分区范围从而提升查询性能medium
并发性对比(说明要点)共享表并发读写共享表允许并发读写high
未共享的分区表并发写限制不允许多线程对相同分区同时写入high
常规内存表与键值内存表持久化支持不支持数据持久化;节点重启后内存数据将全部丢失high
流数据表持久化前提条件只有空的流数据表才支持持久化;需先配置persistenceDir,再使用enableTableShareAndPersistence共享并持久化到磁盘high
流数据表持久化内存保留最新记录数默认值默认保留最新10万条记录在内存中high
流数据表持久化持久化模式选项可设定异步/同步、压缩/不压缩;通常异步模式吞吐量更高medium
流数据表持久化(重启后)加载行为系统重启后再次执行enableTableShareAndPersistence,会将磁盘中所有数据加载到内存high
MVCC内存表持久化支持支持持久化;创建时可指定持久化路径;重启后可用loadMvccTable加载high
表结构操作(说明要点)addColumn限制分区表以及MVCC内存表不能通过addColumn函数新增列high
分区表结构操作(说明要点)通过update新增列分区表可通过update语句新增列high
流数据表结构操作(说明要点)通过update新增列流数据表不允许修改,因此不能通过update语句新增列high
DolphinDB 内存表能力总体总结性结论支持4种内存表,并引入共享与分区概念,基本满足内存计算与流计算需求medium