存算分离模式下借助本地缓存提升查询性能

EMR Serverless StarRocks 3.1.0版本正式支持存算分离模式。在该模式下计算和存储资源被解耦,极大地优化了资源利用效率和成本。为了进一步提升查询性能,该模式充分利用本地缓存技术,将热数据存储于计算节点的本地磁盘中。当查询请求命中本地缓存时,存算分离集群的查询性能与存算一体集群相当。此外,通过将数据从StarRocks BE本地磁盘迁移到阿里云对象存储OSS,可以显著降低数据存储成本。

前提条件

已在OSS上创建存储空间,详情请参见控制台创建存储空间

步骤一:创建并连接Serverless StarRocks存算分离实例

创建并连接Serverless StarRocks实例详情,请参见快速开启EMR Serverless StarRocks存算分离模式

重要
  • 选择3.1版本,打开存算分离开关,选择OSS Location

    建议为StarRocks实例分配独立的OSS Bucket,以便更好地管理、统计和监控存算分离实例在OSS上的存储、带宽和API使用情况。

  • 请勿擅自修改存算分离实例使用的Bucket,否则可能会引起数据丢失。

步骤二:创建存算分离数据库及数据表

  1. 创建数据库cloud_db和数据表detail_demo

    说明

    存算分离(云原生)表的建表语法与存算一体完全兼容。

    CREATE DATABASE cloud_db;
    USE cloud_db;
    CREATE TABLE IF NOT EXISTS detail_demo (
        recruit_date  DATE           NOT NULL COMMENT "YYYY-MM-DD",
        region_num    TINYINT        COMMENT "range [-128, 127]",
        num_plate     SMALLINT       COMMENT "range [-32768, 32767] ",
        tel           INT            COMMENT "range [-2147483648, 2147483647]",
        id            BIGINT         COMMENT "range [-2^63 + 1 ~ 2^63 - 1]",
        password      LARGEINT       COMMENT "range [-2^127 + 1 ~ 2^127 - 1]",
        name          CHAR(20)       NOT NULL COMMENT "range char(m),m in (1-255) ",
        profile       VARCHAR(500)   NOT NULL COMMENT "upper limit value 65533 bytes",
        ispass        BOOLEAN        COMMENT "true/false")
    DUPLICATE KEY(recruit_date, region_num)
    DISTRIBUTED BY HASH(recruit_date, region_num)
    PROPERTIES (
      "replication_num" = "1"
    );
  2. 查看表的基本信息。

    1. 通过以下命令,可以获取到数据库DbId

      SHOW PROC '/dbs';

      返回信息如下所示。

      image

    2. 通过以下命令,查看表的详细信息。

      SHOW PROC '/dbs/10061';

      示例代码中的10061为前一步骤中获取到的DbId,返回信息如下所示。image

      其中,Type字段标示出存算分离模式下的数据表类型是CLOUD_NATIVE。StoragePath字段为表在OSS对象存储中的路径,通过该路径可以定位到存算分离表的数据存储位置。

步骤三:存算分离Cache特性演示

  1. 准备初始数据环境。

    通过一些可观测性手段验证和展示StarRocks存算分离的本地Cache特性,特别关注缓存开启(datacache.enable)和关闭状态对导入和查询性能的影响。在该测试中,创建了两个测试表,并使用Broker Load方式导入测试数据。

  2. 创建以下数据表。

    • catalog_sales:开启本地缓存。

    • catalog_sales_nocache:关闭本地缓存。

    USE cloud_db;
    --创建catalog_sales、catalog_sales_async、catalog_sales_nocache表。
    create table if not exists catalog_sales(
      cs_order_number bigint,
      cs_item_sk bigint,
      cs_sold_date_sk bigint,
      cs_sold_time_sk bigint,
      cs_ship_date_sk bigint,
      cs_bill_customer_sk bigint,
      cs_bill_cdemo_sk bigint,
      cs_bill_hdemo_sk bigint,
      cs_bill_addr_sk bigint,
      cs_ship_customer_sk bigint,
      cs_ship_cdemo_sk bigint,
      cs_ship_hdemo_sk bigint,
      cs_ship_addr_sk bigint,
      cs_call_center_sk bigint,
      cs_catalog_page_sk bigint,
      cs_ship_mode_sk bigint,
      cs_warehouse_sk bigint,
      cs_promo_sk bigint,
      cs_quantity int,
      cs_wholesale_cost decimal(7,2),
      cs_list_price decimal(7,2),
      cs_sales_price decimal(7,2),
      cs_ext_discount_amt decimal(7,2),
      cs_ext_sales_price decimal(7,2),
      cs_ext_wholesale_cost decimal(7,2),
      cs_ext_list_price decimal(7,2),
      cs_ext_tax decimal(7,2),
      cs_coupon_amt decimal(7,2),
      cs_ext_ship_cost decimal(7,2),
      cs_net_paid decimal(7,2),
      cs_net_paid_inc_tax decimal(7,2),
      cs_net_paid_inc_ship decimal(7,2),
      cs_net_paid_inc_ship_tax decimal(7,2),
      cs_net_profit decimal(7,2)
    )
    duplicate key (cs_order_number, cs_item_sk)
    distributed by hash(cs_order_number, cs_item_sk) buckets 90
    properties(
      "replication_num"="1", 
      "datacache.enable" = "true"
    );
    
    
    --创建catalog_sales_nocache表。
    create table if not exists catalog_sales_nocache(
      cs_order_number bigint,
      cs_item_sk bigint,
      cs_sold_date_sk bigint,
      cs_sold_time_sk bigint,
      cs_ship_date_sk bigint,
      cs_bill_customer_sk bigint,
      cs_bill_cdemo_sk bigint,
      cs_bill_hdemo_sk bigint,
      cs_bill_addr_sk bigint,
      cs_ship_customer_sk bigint,
      cs_ship_cdemo_sk bigint,
      cs_ship_hdemo_sk bigint,
      cs_ship_addr_sk bigint,
      cs_call_center_sk bigint,
      cs_catalog_page_sk bigint,
      cs_ship_mode_sk bigint,
      cs_warehouse_sk bigint,
      cs_promo_sk bigint,
      cs_quantity int,
      cs_wholesale_cost decimal(7,2),
      cs_list_price decimal(7,2),
      cs_sales_price decimal(7,2),
      cs_ext_discount_amt decimal(7,2),
      cs_ext_sales_price decimal(7,2),
      cs_ext_wholesale_cost decimal(7,2),
      cs_ext_list_price decimal(7,2),
      cs_ext_tax decimal(7,2),
      cs_coupon_amt decimal(7,2),
      cs_ext_ship_cost decimal(7,2),
      cs_net_paid decimal(7,2),
      cs_net_paid_inc_tax decimal(7,2),
      cs_net_paid_inc_ship decimal(7,2),
      cs_net_paid_inc_ship_tax decimal(7,2),
      cs_net_profit decimal(7,2)
    )
    duplicate key (cs_order_number, cs_item_sk)
    distributed by hash(cs_order_number, cs_item_sk) buckets 90
    properties(
      "replication_num"="1",
      "datacache.enable" = "false"
    );
  3. 数据导入测试。

    1. 上传测试数据到OSS。

      说明

      本文示例通过ECS实例执行以下命令,您也可以在本地执行。创建ECS实例的具体操作,请参见通过控制台使用ECS实例(快捷版)

      1. 通过以下命令,编辑upload.sh。

        vim upload.sh
      2. 在upload.sh中新增以下内容。

        #!/bin/bash
        
        # 日期时间
        date_time=`date +%Y-%m-%d-%H-%M-%S`
        
        yum install -y wget unzip
        mkdir -p /data/
        curl https://gosspublic.alicdn.com/ossutil/install.sh | sudo bash
        wget  -O catalog_sales.zip  "https://starrocks-oss.oss-cn-beijing.aliyuncs.com/public-access/catalog_sales.zip" &&  unzip -o catalog_sales.zip -d /data/
        echo download data finish
        upload_url=$1
        #ossutil cp -r /data/   ${upload_url}
        
        endpoint="oss-cn-****-internal.aliyuncs.com"
        accessKeyId="LTAI5tJKzJYFWJXtchWG****"
        accessKeySecret="oRHrl4fIR5NMlOTRvo99qDkLUf****"
        
        echo ossutil64 -e ${endpoint} -i ${accessKeyId} -k ${accessKeySecret} cp -r /data/   ${upload_url}
        ossutil64 -e ${endpoint} -i ${accessKeyId} -k ${accessKeySecret} cp -r -f /data/   ${upload_url}
        echo success for data upload

        请根据实际情况替换文件中的endpointaccessKeyIdaccessKeySecret

        参数

        说明

        endpoint

        访问OSS的EndPoint。例如,oss-cn-hangzhou-internal.aliyuncs.com。

        accessKeyId

        访问OSS的AccessKey ID。

        accessKeySecret

        访问OSS的AccessKey Secret。

      3. 执行以下命令,运行upload.sh并上传测试数据到OSS。

        sh upload.sh 'oss://yourBucketName/tcp_ds/'
        说明

        oss://yourBucketName/tcp_ds/为测试数据上传的路径。

    2. 使用Broker Load导入测试数据(约10 GB)。

      -- 导入数据到catalog_sales。
      LOAD LABEL cloud_db.catalog_sales_0001
      (
        DATA INFILE("file_path")
        INTO TABLE catalog_sales
        format as "parquet"
      )
      WITH BROKER 'broker'
      (
        "fs.oss.accessKeyId" = "yourKey",
        "fs.oss.accessKeySecret" = "yourSecret ",
        "fs.oss.endpoint" = "yourBucketEndpoint"
      );
      
      
      -- 导入数据到catalog_sales_nocache。
      LOAD LABEL cloud_db.catalog_sales_0003
      (
        DATA INFILE("file_path")
        INTO TABLE catalog_sales_nocache
        format as "parquet"
      )
      WITH BROKER 'broker'
      (
        "fs.oss.accessKeyId" = "yourKey",
        "fs.oss.accessKeySecret" = "yourSecret ",
        "fs.oss.endpoint" = "yourBucketEndpoint"
      );

      参数

      说明

      file_path

      为测试数据的路径,请根据实际情况修改。例如,oss://<yourBucketName>/tcp_ds/data/*.parquet。

      fs.oss.accessKeyId

      访问OSS的AccessKey ID。

      fs.oss.accessKeySecret

      访问OSS的AccessKey Secret。

      fs.oss.endpoint

      访问OSS的EndPoint。例如,oss-cn-hangzhou-internal.aliyuncs.com。

    3. 导入任务页面,可以查看测试结果。

      测试结果如下表所示。

      表名称

      本地缓存

      表模型

      导入用时

      catalog_sales

      开启

      明细表

      1m21s

      catalog_sales_no_cache

      未开启

      明细表

      1m20s

      测试结果表明,在存储与计算分离的场景中,启用缓存对导入性能的影响极为有限。

  4. 数据查询测试。

    针对开启本地缓存和不开启本地缓存两种场景进行了测试,以评估本地缓存对查询性能的影响。在StarRocks的存算分离模式下,Query执行引擎会在查询执行过程中记录访问缓存和对象存储OSS的指标,并将其记录在Profile中。因此,我们可以使用Profile工具来查看相关指标。

    -- 最大Query超时时间。
    set global query_timeout=1200;
    
    -- 查询catalog_sales开启本地缓存。
    select cs_item_sk,cs_bill_customer_sk from cloud_db.catalog_sales group by cs_item_sk,cs_bill_customer_sk order by cs_item_sk desc limit 100;
    
    -- 查询catalog_sales_nocache关闭本地缓存。
    select cs_item_sk,cs_bill_customer_sk from cloud_db.catalog_sales_nocache group by cs_item_sk,cs_bill_customer_sk order by cs_item_sk desc limit 100;

    慢查询或者全部查询页面,找到对应的Query,在执行详情页签可以看到Profile执行树,找到CONNECTOR_SCAN节点,右侧指标中主要关注CompressedBytesReadLocalDisk(从本地缓存读取)和CompressedBytesReadRemote(从远端OSS对象存储读取)两个指标。

    本示例中,catalog_sales表开启了本地缓存,指标值CompressedBytesReadLocalDisk>0,因此可以确定查询全部命中了本地缓存。

    image

    catalog_sales_nocache表没有开启本地缓存,指标值CompressedBytesReadLocalDisk=0,查询数据未命中本地缓存,数据全部来自远端OSS对象存储。

    image

    通过对两个查询的执行耗时对比,进一步验证了结论:当查询命中本地缓存时,查询速度更快。

步骤四:对比存算分离和存算一体的性能

以下内容通过一个测试案例,为您展示了存算分离带本地缓存和存算一体两种模式下的查询性能对比。您可以使用TPC-H测试集进行更详细的性能对比测试,详情请参见TPC-H性能测试说明

  1. 准备数据环境。

    • 集群资源配置:1FE(8CU)+3BE(算力:16CU|存储:1000 GB)。

    • 集群参数:使用默认设置,存算分离集群开启本地缓存。

    • 数据量:500 GB(sf=500),经过压缩后约为180 GB。

  2. 测试结果。

    • 存算一体22条SQL总计用时:302.063 seconds。

    • 存算分离22条SQL总计用时(第2次执行时开启本地缓存的情况下):333.390 seconds。

    根据TPC-H的结果显示,在开启本地缓存的情况下,存算分离和存算一体的查询性能基本相同。image.png

相关文档