• Velox Types介绍和源码解析


    Velox 支持 scalar(有大小没有方向)类型和复杂类型。标量类型分为一组固定的物理类型和一组可扩展的逻辑类型。物理类型决定数据在内存中的布局。逻辑类型向物理类型添加附加语义。

    Phsical Types

    每个物理类型都是用c++ type实现的,不会存储实际数据,下表是支持的物理类型、其对应的c++类型和每个值所需的固定宽度字节

    Physical TypeC++ TypeFixed Width (bytes)
    BOOLEANbool0.125 (i.e. 1 bit)
    TINYINTint8_t1
    SMALLINTint16_t2
    INTEGERint32_t4
    BIGINTint64_t8
    HUGEINTint128_t16
    REALfloat4
    DOUBLEdouble8
    TIMESTAMPstruct Timestamp16
    VARCHARstruct StringView16
    VARBINARYstruct StringView16
    OPAQUEstd::shared_ptr16
    UNKNOWNstruct UnknownValue0

    除了VARCHAR and VARBINARY 所有的物理类型都有和 c++类型一对一的映射。c++类型也在vector类中用作模板参数。例如,64 位整数向量表示为 FlatVector,其类型为 BIGINT。

    OPAQUE类型可用于定义自定义类型。OPAQUE类型必须与唯一的std::type_index一起指定。此类型的值必须以std::shared_ptr提供,其中T是C++类型。下面给出了有关何时使用OPAQUE类型定义自定义类型的更多详细信息。

    VARCHAR、VARBINARY、OPAQUE 每个值使用可变的字节数。这些类型在 C++ 类型中存储固定宽度部分,在其他地方存储可变宽度部分。所有其他类型的每个值都使用固定宽度字节,如上表所示。VARCHAR和VARBINARY FlatVector将每个值的固定宽度部分存储在StringView中。StringView是一个结构,包含一个4字节大小字段、一个4字节前缀字段和一个指向可变宽度部分的8字节字段指针。每个值的可变宽度部分存储在stringBuffers中。OPAQUE类型将可变宽度部分存储在FlatVector之外。

    UNKNOWN类型用于表示unknown type的empty或全为null的vector。例如,SELECT array() 返回 ARRAY(UNKNOWN()),因为无法确定元素的类型。这是有效的,因为array中没有元素。array方法作用:返回具有给定元素的数组

    TIMESTAMP类型用于表示特定的时间点。 TIMESTAMP 定义为自 UNIX epoch 以来秒和纳秒的总和。struct Timestamp 包含一个表示秒的 64 位有符号整数和表示纳秒的另一个 64 位无符号整数。纳秒表示时间戳的高精度部分,小于1秒。纳秒的有效范围是 [0, 10^9)。纪元之前的时间戳是使用负秒值指定的。

    Logical Types

    逻辑类型由物理类型支持并包含附加语义。同一物理类型可以支持多种逻辑类型。因此,了解 C++ 类型不足以推断逻辑类型。下表显示了支持的逻辑类型及其相应的物理类型。

    Logical TypePhysical Type
    DATEINTEGER
    DECIMALBIGINT if precision <= 18, HUGEINT if precision >= 19
    INTERVAL DAY TO SECONDBIGINT
    INTERVAL YEAR TO MONTHINTEGER

    Custom Types

    大多数自定义类型可以表示为逻辑类型,并且可以通过扩展现有的物理类型来构建。例如,下面描述的Presto类型是通过扩展物理类型来实现的。当没有物理类型可用于支持逻辑类型时,必须使用OPAQUE类型。

    Complex Types

    Velox 支持 ARRAY、MAP 和 ROW 复杂类型。复杂类型由标量(scalar)类型组成,可以与其他复杂类型嵌套。

    例如: MAP 是一个复杂类型,其key是标量类型 INTEGER,value是元素类型为 BIGINT 的复杂类型 ARRAY。

    Array类型包含其元素类型。 Map类型包含键类型和值类型。row类型包含其字段类型及其名称。

    源码解析

    Type 定义了velox的内置类型的一些信息提供一些接口,不存储实际的数据

    枚举类型TypeKind定义类型的种类

    enum class TypeKind : int8_t {
      BOOLEAN = 0,
      TINYINT = 1,
      SMALLINT = 2,
      INTEGER = 3,
      BIGINT = 4,
      REAL = 5,
      DOUBLE = 6,
      VARCHAR = 7,
      VARBINARY = 8,
      TIMESTAMP = 9,
      HUGEINT = 10,
      // Enum values for ComplexTypes start after 30 to leave
      // some values space to accommodate adding new scalar/native
      // types above.
      ARRAY = 30,
      MAP = 31,
      ROW = 32,
      UNKNOWN = 33,
      FUNCTION = 34,
      OPAQUE = 35,
      INVALID = 36
    };
    

    下面是Type的继承结构

    				             Type
    				               |
    				          TypeBase
              				 /      |       \
    		        ScalarType  ArrayType   MapType
    

    Type 是抽象基类继承自Tree,复杂类型子类例如ArrayType和MapType会包含子类型,从而形成Tree

    TypeBase:从Type派生而来的中间类,借助TypeTraits实现方法,TypeTraits使用模板特化技术根据TypeKind定义以下属性

    template 
    struct TypeTraits {};
    
    template <>
    struct TypeTraits {
      using ImplType = ScalarType; // velox实现的 type
      using NativeType = bool; // c++ type,对于无法映射的复杂类型这里是void
      using DeepCopiedType = NativeType;
      static constexpr uint32_t minSubTypes = 0;
      static constexpr uint32_t maxSubTypes = 0;
      static constexpr TypeKind typeKind = TypeKind::BOOLEAN;// TypeKind
      static constexpr bool isPrimitiveType = true; // 是否为c++原生类型
      static constexpr bool isFixedWidth = true;// 是否为固定长度
      static constexpr const char* name = "BOOLEAN";//类型名
    };
    
    class TypeBase : public Type {
     public:
      using NativeType = TypeTraits;
    
      TypeBase() : Type{KIND} {}
    
      bool isPrimitiveType() const override {
        return TypeTraits::isPrimitiveType;
      }
    
      bool isFixedWidth() const override {
        return TypeTraits::isFixedWidth;
      }
    
      const char* kindName() const override {
        return TypeTraits::name;
      }
    
      const char* name() const override {
        return TypeTraits::name;
      }
    
      const std::vector& parameters() const override {
        static const std::vector kEmpty = {};
        return kEmpty;
      }
    };
    

    ScalarType:标量类型类模板,标量对象只含单个元素,以下类型都从ScalarType类模板实例而来:

    • 各种整型类型(对应8-64位宽度的整型,TinyintType、SmallintType、IntegerType、BigintType)
    • RealType、DoubleType
    • VarcharType、VarbinaryType
    • TimestampType、DateType、IntervalDayTimeType
    using IntegerType = ScalarType;
    using BooleanType = ScalarType;
    

    ArrayType:对应数组类型,包含一个TypePtr child_成分(也就是Tree的子节点),数组类型所有内部元素的类型相同(只有一个)。

    MapType:对应映射类型,包含TypePtr key_ + TypePtr value_两个成分,从Key映射到Value,符合一般映射的语义。

    RowType:对应行类型TypeKind=ROW,代表行的每一列的meta信息,包括2个成分。

    • 一个string name_的列表(各列的名称)
    • 一个TypePtr children_的列表(各列的Type信息)

    类型工厂:TypeFactory

    类模板TypeFactory实现create()接口,用于创建某种具体类型,参考设计模式的工厂方法。

    对于标量类型,通常只需要一个唯一的类型实例,因为标量类型不包含额外状态信息(额外是指相对于Type本身状态外)。

    对于非标量类型(TypeKind>=30),比如ArrayType、MapType、RowType等类型,因为每个各MapType的Key、Value并不相同,所以需要针对每个类型创建对应的Type。

    template 
    struct TypeFactory {
      static std::shared_ptr::ImplType> create() {
        return TypeTraits::ImplType::create();
      }
    };
    
    template <>
    struct TypeFactory {
      static std::shared_ptr create() {
        return std::make_shared();
      }
    };
    

    利用宏和模板提供了获取类型实例的方法使得INTEGER()等价于return ScalarType::create();

    #define VELOX_SCALAR_ACCESSOR(KIND) \
      std::shared_ptr> KIND()
    #define VELOX_DEFINE_SCALAR_ACCESSOR(KIND)                   \
      std::shared_ptr> KIND() { \
        return ScalarType::create();             \
      }
    VELOX_DEFINE_SCALAR_ACCESSOR(INTEGER); 
    
    

    CppToType支持根据c++ type获取velox type的相关信息(保存在TypeTraits),实现方法也是模板特化

    template  struct CppToType {};
    template <> struct CppToType : public CppToTypeBase {};
    struct CppToTypeBase : public TypeTraits {
      static auto create() {
        return TypeFactory::create();
      }
    };
    
    CppToType::typeKind // 获取c++ type对应的TypeKind
    

    参考

    https://facebookincubator.github.io/velox/develop/types.html

  • 相关阅读:
    JavaScript客户端操作
    完全免费的PDF软件
    算法通关村第九关-青铜挑战二分查找算法
    k8s 容器化技术 1
    JWT的原理及实际应用
    视频汇聚/视频云存储/视频监控管理平台EasyCVR安全检查的相关问题及解决方法2.0
    视频暂停发送逻辑
    思维模型 周期
    计算机组成原理-第三章 存储系统【期末复习|考研复习】
    优化算法 - 学习率调度器
  • 原文地址:https://blog.csdn.net/weixin_45857154/article/details/139480654