• GreenPlum AOCO列存读IO原理


    GreenPlum AOCO列存读IO原理

    GP自带AOCO列存,它的IO和heap表的IO是分开的。Heap表的脏数据由checkpoint或后台write进程刷写,也就是FlushBuffer函数调用smgrwrite。由magnetic disk storage manager管理IO模块。但是AOCO列存则是由本身进行管理,由函数BufferedAppendWrite完成脏页的刷写。同理,AOCO列存的读也是由本身管理,由函数BufferedReadIo完成加载到内存。本文重点介绍AOCO是如何加载数据页的

    1、相关结构体

    我们先看下列存扫描涉及的相关结构体及其之间的关系,如下图所示:

    99347a3806fad5f3a95925e42f136e53.png

    1)函数scan_begin->aocs_beginscan初始化AOCSScanDesc结构,该结构与IO相关的主要是columnScanInfo结构,包含proj_atts即扫描投影列的列号数组;ds数组大小是列的个数,也就是每个投影列为一个成员ds[i],即DatumStreamRead

    2)DatumStreamRead描述每个AO列的读相关信息。包含:

    (1)maxAoBlockSize表示最大AO块大小,该值大小来自pg_attribute_encoding系统表的option指定的大小。默认是32KB。

    (2)buffer_beginp:指向一个block中的value头位置,将其值赋予blockRead的buffer_beginp。指向largeReadMemory某个位置。

    acc->buffer_beginp=AppendOnlyStorageRead_GetBuffer(&acc->ao_read)

    函数datumstreamread_block_get_ready中将其值给blockRead的buffer_beginp进行管理。

    8a455f408722eb6b1b5bc924b61ba7dc.png

    可以看出largeReadLen其实就是从磁盘上一次读入buffer的大小。

    3)DatumStreamBlockRead:管理一个block中tuple的读取

    4)AppendOnlyStorageRead:管理IO

    (1)maxBufferLen:一个block大小,请求读的最大大小

    (2)largeReadLen:2*maxBufferLen大小

    (3)storageAttributes:每一列的属性,比如是否压缩、压缩算法、压缩级别等

    (4)bufferedRead:这个是真正管理buffer的

    5)BufferedRead:管理IO的buffer,包括

    (1)maxBufferLen:1个block大小,请求读的最大大小

    (2)maxLargeReadLen:2个block大小,IO的最大请求

    (3)memory:总的IO buffer,大小是memoryLen,其实是上述2个值的和,即3个block大小

    (4)beforeBufferMemory:memory的前一部分,用于使得block连续

    (5)largeReadMemory:IO的内容都是加载到这里的

    (6)largeReadPosition:seg文件的已读大小

    (7)bufferOffset和bufferLen:bufferLen本次请求读的大小,bufferOffset为在largeReadMemory中的读偏移

    2、blockRead中memory的管理

    分为两种情况,一种是请求的block页全部在largeReadMemory中,另一种是被截断了,正好在largeReadMemory末尾位置仍旧不是完整的。

    2.1 请求的block全部在largeReadMemory

    64cb02a6ecbbf5531d8b661d3cafd4c9.png

    1)BufferedReadIo一次从磁盘上读入2个页大小的内容到BufferedRead.largeReadMemory中

    2)aocs_getnext函数需要从该buffer读取一个tuple:

    (1)先读取最小页头(包含crc,但不包含firstRowNum),大小是16字节

    e85692a090532f78ca00e9992f513fbd.png

    (2)AppendOnlyStorageFormat_GetHeaderInfo函数获取页头信息,AppendOnlyStorageRead.storageAttributes.checksum标记是否开启了checksum

    (3)若由firstRowNum,则页头大小需要申请24字节

    (4)BufferReadGrowBuffer函数重新读取largeMemoryBuffer,将需要的页头大小扩展到24字节,并从中解析出数据部分大小。storageRead->current.overallBlockLen=页头+数据部分大小

    (5)检查checksum

    (6)返回value部分,每个value都由value头+数据组成,将这个值作为slot的value指针返回。

    (7)实际上TupleSlot的datum值指向的是largeReadMemory内存的某个位置

    2.2 请求的block没全部在largeReadMemory

    0d3b8630141d325d3e7eaf4188fc5567.png

    这种情况发生在重新获取包括firstRowNum或者整个block data的场景中:

    1)当请求的大小超出largeReadMemory的时候,也就是需要的数据并没有全部加载进来,此时为了保证一个block连续,将头部内容拷贝到beoreBufferMemory中。当然需要先计算处理剩余多少,从beoreBufferMemory尾部开始放以便和后续的同一个block的内容连续。

    2)此时在返回的页头是beoreBufferMemory中的指针,也就是数据是从beforeBufferMemory中开始的。

    到此大概就了解了AOCO是如何加载数据的了,希望给大家带来一些启发。

  • 相关阅读:
    【OpenCV】红绿灯识别 轮廓识别 C++ OpenCV 案例实现
    与机器学习相比,人类的学习包括视觉、听觉、触觉、嗅觉、味觉的串并行混合学习...
    成百上千人的签到现场?这个技术你值得拥有
    C# 中的“智能枚举”:如何在枚举中增加行为
    keil5debug无法进行调试
    【技术美术知识储备】模型与材质基础
    CV5200无线WiFi通信模组,远距离无线传输方案,助力无线视频传输通信
    UE4碰撞射线检测2
    保障通航桥梁安全,创新边缘计算技术助力桥梁主动防撞预警系统
    electron桌面应用webSoket实时弹框提示实现
  • 原文地址:https://blog.csdn.net/yanzongshuai/article/details/128059831