分区表

表分区对数据的存储方式和位置进行行级控制。

分区的分类

Hubble中分区表分为两种:

  • 值分区:枚举每个分区的所有可能值。当可能值的数量很少时,列值分区是一个不错的选择。
  • 范围分区:通过指定下限和上限,为每个分区指定一个连续的值范围。当可能值的数量太大而无法明确列出时,范围分区是一个不错的选择。

按列值分区

要按列对表进行分区,请PARTITION BY LIST在创建表时使用语法。在定义列分区时,如果没有任何行符合已定义分区的要求,您还可以设置DEFAULT作为包罗万象的分区。

按范围分区

要按范围定义表分区,请PARTITION BY RANGE在创建表时使用语法。在定义范围分区时,您可以使用Hubble定义的MINVALUEMAXVALUE参数分别定义范围的下限和上限。

Hubble使用分区表的时候,分区字段必须是主键或复合主键的一部分

分区的查询

首先查看表的CREATE TABLE语句

create table  cust_info (
       cust_id INT NOT NULL,
       city VARCHAR(10) NOT NULL,
       cust_name VARCHAR(10) NULL,
       address VARCHAR(10) NULL,
       cust_card VARCHAR(10) NULL,
       CONSTRAINT "primary" PRIMARY KEY (city ASC, cust_id ASC),
       FAMILY "primary" (cust_id, city, cust_name, address, cust_card)
        ) PARTITION BY LIST (city) (
          PARTITION p1 VALUES IN (('shanghai'), ('nanjing')),
          PARTITION p2 VALUES IN (('beijing'), ('tangshan') ),
          PARTITION p3 VALUES IN (('xian'), ('xining')),
          PARTITION DEFAULT VALUES IN (default)
        );
  • 过滤非索引列

假设您要查询表以获取有关特定用户的信息,但您只知道该用户的名称

explain select * from cust_info where cust_name='zhangsan';
                                  info
------------------------------------------------------------------------------------
  distribution: full
  vectorized: true

  • filter
  │ estimated row count: 1
  │ filter: cust_name = 'zhangsan'
  │
  └── • scan
        estimated row count: 1 (100% of the table; stats collected 41 minutes ago)
        table: cust_info@primary
        spans: FULL SCAN

该查询返回相同的结果,但由于cust_name不是索引列,该查询执行跨所有分区值的全表扫描。

  • 在分区列上过滤

如果知道哪个分区包含您正在查询的数据,则在用于该分区的列上使用过滤器(例如,WHERE子句)可以通过将扫描限制到包含数据的特定分区来进一步提高性能你正在查询。

现在假设您知道用户的姓名和位置。您可以使用对用户名和城市的过滤器来查询表

explain select * from cust_info where cust_name='zhangsan' and city='beijing';
                                       info
-----------------------------------------------------------------------------------
  distribution: local
  vectorized: true

  • filter
  │ estimated row count: 1
  │ filter: cust_name = 'zhangsan'
  │
  └── • scan
        estimated row count: 1 (100% of the table; stats collected 3 minutes ago)
        table: cust_info@primary
        spans: [/'beijing' - /'beijing']

该表返回与以前相同的结果,但成本要低得多,因为查询扫描现在只跨越beijing分区值。

分区表举例

  • 按列值分区 ,用到PARTITION BY LIST语句
CREATE TABLE t1 (
    id INT ,
    name STRING,   
    az STRING,
    create_ DATE,
    PRIMARY KEY (az,id))
    PARTITION BY LIST (az) (
      PARTITION p1 VALUES IN ('A'),
      PARTITION p2 VALUES IN ('B'),
      PARTITION p3 VALUES IN ('C','D'),
      PARTITION DEFAULT VALUES IN (default)
    );

分区结构查询

show partitions from table t1;
  • 按范围分区 ,用到PARTITION BY RANGE语句
CREATE TABLE t2 (
   cust_id INT ,
   cust_name STRING,
   email STRING,   
   create_date DATE,
   PRIMARY KEY (create_date, cust_id)	
   )
   PARTITION BY RANGE(create_date)
      (PARTITION p1 VALUES FROM (MINVALUE) TO ('2021-06-30'),
      PARTITION p2 VALUES FROM ('2021-06-30') TO (MAXVALUE));

分区结构查询

show partitions from table t2;

重设分区表

通过使用该PARTITION BY命令的子命令来实现这一点ALTER TABLE

ALTER TABLE t2 PARTITION BY RANGE (create_date) (
    PARTITION p1 VALUES FROM (MINVALUE) TO ('2021-03-31'),
    PARTITION p2 VALUES FROM ('2021-03-31') TO ('2021-06-30'),
    PARTITION p3 VALUES FROM ('2021-06-30') TO ('2021-09-30'),
    PARTITION p4 VALUES FROM ('2021-09-30') TO (MAXVALUE));

取消分区

可以使用以下PARTITION BY NOTHING语法删除表上的分区

alter  table t2 partition by nothing;

不能删除某个特定的分区

Hubble不支持分区表数据的批量加载与删除,如果表需要频繁批量的加载与删除,不建议做表的分区。