Greenplum7有哪些变化
写在2024年01月25日晚
本想尝试按照gp7的官方文档更新一版《Greenplum管理员指南》,刚开始2天就坚持不下去了,一者,跟灿总聊起此事时,灿总以为我可以用爱发电,的确,我反思了,用爱不能发电,再者,官方文档结构过于混乱,不如写篇文章,介绍一下7版本主要的变化。下面是从官方文档摘录的信息,一些内容经过了加工和展开。如之前的文章提到的,GPAdmin客户端和gptool工具包,都对gp7进行了兼容。
1、支持v2的cgroup作为资源组的实现,可以管理io吞吐量和iops,对于磁盘io能力不足的环境,会比较有用,不过,从现在开始,应该广泛使用ssd甚至nvme(实际上过去几年已经很广泛),永远不应该让io成为瓶颈。
2、Resource Group回归了之前的内存管理方案,放弃了在6版本引入的一堆混乱的内存控制算法,我觉得,statement_mem是很好的内存管理方案,足够的灵活和简单。
3、支持Index only的索引扫描,并支持CREATE INDEX的INCLUDE子句,允许在索引查询时不再回表,从而提升索引查询的性能。
4、在AO表上支持Primary Key,Unique Index。我建议,如非特别必要,不要总想着创建索引就能提升性能,OLAP和OLTP完全不同。
5、改善了ANALYZE的性能,以往的ANALYZE仅在heap表上采用抽样算法,现在,在AO表上也采用了抽样算法,大大提升了ANALYZE的性能。也就是说,以前,5版本和6版本发布时说的ANALYZE性能提升,其实,都只是优化了抽样后的算法,直到7版本,才算优化了抽样算法本身。
6、使用ALTER TABLE ... ADD COLUMN ... 命令添加字段时,不再将数据完全重写一遍。这在很多场景会特别有用。比如某通讯公司想要这个功能已经好多年了,因为他们经常加字段,一直苦苦煎熬至今。
7、支持pg的分区语法(ATTACH,DETACH等),gp原有的分区语法也还继续支持,不过新的hash分区策略,不支持老的分区语法。使用新的分区语法,可以创建出各种稀奇古怪的分区表:
以前有个极好的参数gp_max_partition_level,可以控制分区表的级数,我安装数据库时都会把这个参数设置为1,现在7版本把这个参数弄丢了,实在可惜,我一直坚定的支持禁用多级分区。
8、支持多字段组合的统计信息(MCV),对于多字段复杂条件的场景,使用MCV统计信息可能会有助于生成更准确的执行计划。
9、INSERT语句支持ON CONFLICT子句,允许对约束冲突的数据进行UPDATE或者忽略。需要注意的是,这不是merge语法。
10、支持新的索引类型BRIN索引,对于有序数据,该索引可以在保证查询效率的同时,极大降低索引尺寸和维护代价。对于无序数据,则仍应该使用btree等索引,BRIN索引不是万能索引,不能取代btree索引。
11、支持行级别的安全策略。在用户查询时,该策略体现为一个scan的filter。
12、支持JIT即时编译,在有些场景可能会带来性能的改善。不过,实际测试表明,对于生产场景,大概率不会带来显著的性能提升。
13、支持hash索引。这也不是万能索引,主要适用场景是,对于字段尺寸特别大的情况,hash索引可以降低索引尺寸。但是,hash索引是信息丢失的,只能用于等值条件,非等值条件时索引失效。
14、内置支持全文检索功能。我没有测试过,但我想说一点,gptext怎么办。
15、增加了一些以gp_stat_progress_开头的视图,可以查看ANALYZE、CLUSTER、CREATE INDEX、VACUUM、COPY和BASE_BACKUP等操作的进度情况,真的等着急的时候,可以试试能不能缓解一些焦虑。
16、缺省打开了autovacuum,会自动对系统表进行VACUUM和ANALYZE操作,并对用户表进行ANALYZE操作。INSERT,UPDATE和DELETE影响的数据量大于下面的计算结果时,会自动对操作的表进行ANALYZE操作(自动ANALYZE有延迟,不与当前事务同步):
autovacuum_analyze_scale_factor × reltuples + autovacuum_analyze_threshold
根据缺省值,用这个公式算出来,大概数据变化量要超过10%才会自动收集统计信息,所以,大概不能依赖这个自动。
17、支持生成列,仅支持STORED属性的生成列,因为pg就是这样。
18、支持存储过程PROCEDURE,支持允许在过程中执行事务控制,看起来更像一个脚本的打包。
19、引入了pgvector模块。这可能就是向量计算紧随大模型的影响,这是向量计算,不是向量化计算。
20、关于外部表,实现上,外部表的实现已经变成了foreign table,为了保持使用习惯,保留了pg_exttable视图,而这个视图的定义是这样的:
而这个函数的实现是这样的:
虽然我看不懂每一句代码,但我可以确定,这就是循环查找,大聪明!
21、gpfdist支持并行压缩数据传输,这个idea最早是我和王凤刚一同探索的,早在2020年,我们就完成了基本论证,证明了这个方法可以极大节省gpfdist服务器的网络输出的带宽,并有效提升带宽受限场景的gpfdist外部表加载的性能,最后,这个功能进入产品时,本人几经争取仅在pr里留下一个名字。
22、gpscp命令改为gpsync命令,实现上就是linux的rsync命令,gpsync的-a参数对应的就是rsync的-a参数,即,归档模式,目录递归拷贝,并保留所有格式和权限等信息。
23、pg_resetxlog命令改名为pg_resetwal。祝愿所有人都永远不需要使用这个命令。
24、pg_dump命令包含了可以包含或者排除叶子分区的参数,其实就是来自pg的分区表特性的影响。
25、pg_tables视图中,不再包含外部表的信息,这个视图似乎没什么用。
26、gp_toolkit变成了扩展EXTENSION。这个一直都是数据库自带,用户并不关心这个变化。
27、CREATE TABLE ... (LIKE ... INCLUDING like_option)语法,其中的like_option支持更多类型,包括:
28、支持在AO表上执行CLUSTER命令。
29、SELECT语句支持NOWAIT和SKIP_LOCKED选项,NOWAIT选项,当有锁冲突时,报错失败,SKIP_LOCKED选项,跳过无法获取行级锁的记录,继续查询其他记录。
30、IMPORT FOREIGN SCHEMA支持从FORIGN SERVER将表映射到本地FOREIGN TABLE。比如:
IMPORT FOREIGN SCHEMA fs LIMIT TO(fs_table) FROM SERVER fdw_test into public;
就是将名称为fdw_test的FORIGN SERVER中fs模式下的名称为fs_table的表映射到当前数据库的public模式下名称为fs_table的表。
之后,查询public.fs_table表,就相当于查询gp_fdw_server_test的fs.fs_table表。
31、DROP命令可以在一条命令中删除多个FUNCTION、OPERATOR、AGGREGATE,这真的是一个无聊的功能,大概永远都不会有人使用。
32、ALTER TABLE命令支持修改WITH属性: appendoptimized、blocksize、orientation、compresstype、compresslevel和checksum。这是真的有价值的功能。
33、新增了一个系统表pg_sequence,记录序列的信息,实际上,序列的信息依然没有被完整记录,有些信息依然要从序列对象本身获取,又是一个无聊的改变。
34、新增了一个名为pg_backend_memory_contexts的系统视图,可以查看后台的内存使用情况,这应该是一个特别有意义的改变。
35、删除了一些系统表和系统视图:
pg_partition_columns pg_partition_encoding pg_partition_rule pg_partition_template pg_stat_partition_operation
pg的分区表设计和gp7以前的版本完全不同,所以,这次的pg大版本升级,不得不做出大量改变,这是不可避免的代价。
36、系统表gp_configuration_history的desc字段名称改为description。毫无意义的改变,应该纯粹是为了适应pg的命名习惯。
37、外部表的扫描时,可以记录除以0、JSON格式错误、非法字符编码等情况,通过调用gp_read_error_log()函数,可以获取到这些异常信息。原文档说是增强了gp_read_error_log()函数,表述显然不对,gp_read_error_log()函数只是查询异常信息,并不是记录异常信息。经过验证,的确,7版本会记录分母为0的情况,而6版本则直接整体失败。
38、引入了array_position()函数和array_positions()函数,用于计算元素在数组中的第一个位置,和,元素在数组中的所有位置。
39、orca不支持多级分区表的查询。orca对复杂的分区表一直不友好。
40、VACUUM新增了AO_AUX_ONLY选项,可以回收AO表的辅助表的空间,困扰数年的问题,终于有了一点进展,以往只能通过ALTER TABLE WITH(REORGANIZE=TRUE)来回收这些空间。现在,不指定AO_AUX_ONLY选项,VACUUM也会回收AO表的辅助表的空间,指定AO_AUX_ONLY选项将只回收AO表辅助表的空间。说起来很乱,其实,只要VACUUM的时候能回收,似乎并不需要单独回收,这个选项大概不会有人真的使用。
41、对于AOCO表,允许COPY时选择部分字段,就像这样:
COPY pg_class(oid) TO 'stdout';
然后会收到一个报错:
ERROR: relative path not allowed for COPY to file
这真的是一个奇怪的设计,不知道这比COPY (SELECT)哪里高级,没用的知识又增加了。
42、pg_appendonly系统表中不再记录表的存储属性了,而是,只在pg_class的reloptions字段中存储,大概研发也知道了,多年来一直存在两者不一致的情况。而且,实际上,除非要进行一些元数据处理,用户往往根本不关心这些信息。
43、删除了createlang和droplang命令。其实还有一堆无用的命令,比如:createdb、dropdb、createuser、dropuser等。
44、删除了Greenplum MapReduce,从十几年前跟Hadoop套近乎,至今已经十几年了(可不就是十几年么),终于删了这种没用的垃圾。任何产品的重点都应该是精而专,而不是广而糙。
45、不再支持QuickLZ压缩方法,实际上,这个所谓的专利压缩方法,从来就没有人用过,有了zstd之后,就更不可能有人用了。打开gp_quicklz_fallback参数之后,数据库会自动将QuickLZ压缩转为zstd,然后你会发现,在7.0版本,所有的压缩都变成了zstd,真的是一个极其低级的bug。
PS:
一直存在的一个恶心功能,叫做,子分区模板,从6到7的升级过程中,因为分区表设计的变化,这个功能引入了无数个bug,个人建议这个功能早该删除,毫无价值,之前的版本也一直存在一些bug,居然十几年都没人发现,可见这个功能大概就是从来没人真的使用过。我在我的多个工具中已经删除了对这个功能的支持。
还有一个外部表可以作为分区表的叶子节点的功能,个人觉得是极其糟糕的设计。我在我的多个工具中已经删除了这个功能的支持。这个功能居然被作为一个很大的亮点宣传了好多年,殊不知,一旦某个分区用的是外部表,SQL就会受到极大的限制。
46、建议用ALTER TABLE REPACK BY代替gpreload,例如:
ALTER TABLE test_ao REPACK BY COLUMNS(a DESC);
这是让数据按照指定字段进行有序存储的方法,相当于重建表,索引也会被重建。
如何升级到7版本:大概目前可以选择的官方工具只有gpcopy,如果使用gptool,则可以更好的完成任意版本的升级。gptool有独一无二的ddl无锁备份,ddl并行恢复,ddl差异比对,数据增量同步,让升级更轻松。