GUC系统参数gp_use_legacy_hashops可以控制建立列分布表时使用传统的哈希算法还是新的哈希算法。新的哈希算法如Greenplum数据库Hash分布——计算哈希值和映射segment文章中列出的。传统的哈希算法就是PostgreSQL数据库所提供的算法。
gp_distribution_policy
首先我们知道创建表时指定分布键就是创建Hash分布表,举个例子说明一下gp_use_legacy_hashops参数的使用。首先我们了解一下pg_am表,其存储了relation access methods(可以看成一个大的目录,heap/btree/hash都是章节),目前仅有表和索引有访问方法,直接select查询该表。我们所要关注的hashops归所于amname为hash的access methods下。因此我们仅仅需要关注其oid为405。
再看pg_opfamily系统表,该系统表记录了上面access methods包含的access methods operator familiy(章节中的小节,每个小节一种operator familiy)。我们知道pg_opfamily的opfmethod列是reference自pg_am oid列的,所以我们这里只列出了opfmethod为405的部分记录的operator familiy。
再次我们看一下pg_opclass表其定义了index access method operator class,每个操作符类定义特定数据类型的索引列和特定索引访问方法的语义。我们挑一个记录看一下,可以看出cdbhash_float8_ops操作符类属于hash am大章节中、处于cdbhash_float8_ops operator familiy小节中。
这时我们再来看看创建hash分布表其分布键的信息存储和分布键列类型所所使用的hash函数信息存储的系统表。创建分布表为t3,然后指定float类型的id作为分布键,通过gp_distribution_policy函数查询到其分布键为第一列,所使用的hash operator class为cdbhash_float8_ops。如下为具体执行结果。
gp_use_legacy_hashops参数涉及的分支
gp_use_legacy_hashops参数涉及cdb_get_opclass_for_column_def、cdbllize_adjust_top_path和get_opclass_name_for_distribution_key三个函数。首先我们看看cdb_get_opclass_for_column_def函数,该函数定义再src/backend/cdb/cdbhash.c文件中,用于在解析CREATE TABLE和ALTER TABLE的DISTRIBUTED BY语句时向系统表查询分布键列类型对应的operator class。如果指定opclassName则直接通过opclassname调用ResolveOpClass函数查找对应的operator class,否则需要通过列类型来查询,这时就要用到gp_use_legacy_hashops参数类:如果指定该参数,先使用get_legacy_cdbhash_opclass_for_base_type确定operator class,如果没有查询到,使用cdb_default_distribution_opclass_for_type函数查询postgres原生operator class;如果没有指定该参数,直接使用cdb_default_distribution_opclass_for_type函数查询postgres原生operator class。
get_legacy_cdbhash_opclass_for_base_type函数其实就是调用getBaseType处理一下postgres domains自定义数据类型,然后就根据类型oid来决定operator class name(就是一个switch case,比如INT2OID就是用cdbhash_int2_ops),最后调用get_opclass_oid函数通过查询pg_opclass获取operator class name对应那行记录的oid字段。
cdb_get_opclass_for_column_def函数在ALTER TABLE SET DISTRIBUTED BY语句为表设置distribution policy的函数ATExecSetDistributedBy、CREATE TABLE AS语句基于DISTRIBUTED BY设置Query->intoPolicy的函数setQryDistributionPolicy、给定用到DistributedBy结构体构建GpPolicy的函数getPolicyForDistributedBy这三种情况下会用到。