• Greenplum数据库数据分片策略Hash分布——GUC gp_use_legacy_hashops


    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。

    select * from pg_am;
     oid  amname    amhandler                  amtype
     2    heap      heap_tableam_handler       t     --> table/materialied views
     403  btree     bthandler                  i     --> index
     405  hash      hashhandler                i
     783  gist      gisthandler                i
     2742 gin       ginhandler                 i
     3434 ao_row    ao_row_tableam_handler     t     --> greenplum新增
     3435 ao_column ao_column_tableam_handler  t     --> greenplum新增
     3580 brin      brinhandler                i
     4000 spgist    spghandler                 i
     7013 bitmap    bmhandler                  i
    

    再看pg_opfamily系统表,该系统表记录了上面access methods包含的access methods operator familiy(章节中的小节,每个小节一种operator familiy)。我们知道pg_opfamily的opfmethod列是reference自pg_am oid列的,所以我们这里只列出了opfmethod为405的部分记录的operator familiy。

    select oid, opfmethod, opfname from pg_opfamily;
     oid   opfmethod   opfname
     ...
     427   405         bpchar_ops
     431   405         char_ops
     435   405         date_ops
     627   405         array_ops
     1971  405         float_ops
     ...
     7100  405         cdbhash_interger_ops
     7101  405         cdbhash_float4_ops
     7102  405         cdbhash_float8_ops
     ...
     7130  405         cdbhash_oid_ops
    

    再次我们看一下pg_opclass表其定义了index access method operator class,每个操作符类定义特定数据类型的索引列和特定索引访问方法的语义。我们挑一个记录看一下,可以看出cdbhash_float8_ops操作符类属于hash am大章节中、处于cdbhash_float8_ops operator familiy小节中。

    select * from pg_opclass;
      oid   opcmethod  opcname            opcnamespace  opcowner  opcfamily opcintype opcdefault opckeytype
      10160 405        cdbhash_float8_ops 11            10        7102      701       f          0   
      ...
    

    这时我们再来看看创建hash分布表其分布键的信息存储和分布键列类型所所使用的hash函数信息存储的系统表。创建分布表为t3,然后指定float类型的id作为分布键,通过gp_distribution_policy函数查询到其分布键为第一列,所使用的hash operator class为cdbhash_float8_ops。如下为具体执行结果。

    create table t3(id float, id1 int, id2 int) distributed by (id);
    select oid from pg_class where relname = 't3';
     oid 
     24582
    select * from gp_distribution_policy where localoid = 24582;
     localoid  policytype  numsegments  distkey  distclass  segments
     24582     p           4            1        10160
    select * from pg_opclass where oid = 10160;
      oid  opcmethod  opcname  opcnamespace  opcowner  opcfamily opcintype opcdefault opckeytype
      10160 405       cdbhash_float8_ops 11  10        7102      701       f          0   
    

    在这里插入图片描述

    gp_use_legacy_hashops参数涉及的分支

    gp_use_legacy_hashops参数涉及cdb_get_opclass_for_column_defcdbllize_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。

    Oid cdb_get_opclass_for_column_def(List *opclassName, Oid attrType){
    	Oid			opclass = InvalidOid;
    	if (opclassName) { opclass = ResolveOpClass(opclassName, attrType, "hash", HASH_AM_OID);
    	}else{
    		if (gp_use_legacy_hashops) opclass = get_legacy_cdbhash_opclass_for_base_type(attrType);
    		if (!opclass) opclass = cdb_default_distribution_opclass_for_type(attrType);		
    		if (!OidIsValid(opclass)) ereport(ERROR,(errcode(ERRCODE_UNDEFINED_OBJECT),errmsg("data type %s has no default operator class for access method \"%s\"",format_type_be(attrType), "hash"),errhint("You must specify an operator class or define a default operator class for the data type."))); /* Same error message as in ResolveOpClass, except for the hint, for consistency. */
    	}
    	return opclass;
    }
    

    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这三种情况下会用到。

  • 相关阅读:
    win10 系统安装 doker 入门详细教程
    【分布式】分布式锁解决方案介绍、DBMS级别乐观、悲观、redis的SETNX实现分布式锁
    站点到站点的流量监控
    iOS 关于键盘监听
    关于ElasticSearch日期格式不一致的异常,可以这么解决
    code:-9907磁盘不足如何处理?帮你整理了几个必备的!
    Java实现ip地址计算
    C++避坑:基类函数有无virtual关键字,差别巨大
    STM32嵌入式开发需要掌握硬件、嵌入式系统、C编程语言以及相关的外设驱动等知识
    胡说八道(24.6.3)— 数字信号处理
  • 原文地址:https://blog.csdn.net/asmartkiller/article/details/127024755