羲和(Halo)2025.01产品动态
本次更新中,其中一个能力是全局临时表的功能。这里所说的全局临时表并不是采用了类似pgtt这样的扩展插件实现的“假”全局临时表,而是和Oracle一样的“真”全局临时表。
PG系的临时表一直饱受诟病,究其原因主要是当前的实现中存在诸多的问题。你可以简单的理解为临时表只是建在pg_temp_xxxx(xxxx是根据会话ID生成的数字,保证每个会话下不同)模式下的普通表(当然在缓存管理上和普通表是不一样的,这里先不管),pg_temp_xxxx在不同的会话下是不一样的,从而实现了隔离,在会话结束时pg_temp_xxxx下的对象会被清除。这是临时表实现的基本思路。那这样的实现有什么不足呢?一是由于会话结束时表会被清除,所以会话每次建立后都得重新创建临时表(这个pgtt可以帮助来做这个事情);二是由于临时表需要不断的删除重建,会导致元数据表膨胀,从而影响系统性能;三是临时表只能建在pg_temp下,对于重名的而定义不一样的临时表就无能为力了,那从Oracle迁移过来的时候就会碰到极大的困难。而市面上PG系的目前都无法解决以上问题。难道这就是PG系的命吗?NO!我们不信命!我们要“逆天改命”!
而要实现这样一个“真”全局临时表,难度有多大呢?我们先来看看最近大火的DeepSeek怎么说:
emmm...看到这样的回答,做基础软件的小伙伴们应该可以稍稍安心了,AI们还得继续努力啊。不过有一点DS是说对了,要实现“真”全局临时表确实是一个极具挑战的高难度任务。
作为全局临时表,首先且核心需要解决的一个问题是表结构定义全局可见而数据私有。为解决改问题,我们实现了临时段技术。所谓的临时段技术,简单点说就是虽然表的元数据是共享的,但是会话在访问表数据时,系统会映射到各自临时生成的数据段上,从而实现了数据隔离。
而在会话退出后,这些临时段也将被清除,但是表的元数据依然存在。我们来看看实际的效果。
我们分别建立两个会话:会话A(2959559)和会话B(2959784)。目前是没有全局临时表GTT_1的。我们在会话A里创建一个全局临时表GTT_1。
在会话A创建完GTT_1后,会话B也就能看到GTT_1了。
会话A在GTT_1的任何DML操作,会话B是不可见的。
同理,会话B在GTT_1的任何DML操作,会话A也是不可见的。
在Oracle模式下,默认的行为ON COMMIT DELETE ROWS,因此在COMMIT后,临时表的数据被清空。
当然也支持ON COMMIT PRESERVE ROWS。
当前的实现支持在全局临时表上创建索引,也支持索引扫描。
当然也支持将全局临时表创建在不同的SCHEMA下!
更重要的是,无论有多少个会话使用过全局临时表,元数据表永远不会膨胀!
目前全局临时表只在Oracle模式下工作,后续该特性也将扩展到PostgreSQL、MySQL的模式。敬请期待!