testbook

表的分桶:CLUSTERED BY子句

为表分桶可以让某些任务(比如取样,map join等)运行得更快。表的分桶在建表时完成。

语法

CREATE TABLE table_name (col_name data_type, col_name data_type, ...)
    CLUSTERED BY (col_name, col_name,...)
        [SORTED BY (col_name, col_name,...)[ASC|DESC]]
    INTO n BUCKETS
说明
  • INTO n BUCKETS指定桶的数量
  • SORTED BY根据指定的键排序。ASC表示升序,DESC表示降序。默认顺序是升序。
  • 和分区键不同,分桶键必须是表中的列。
  • 和分区类似,Inceptor支持单层和多层分桶
  • 举例:单层分桶
    [$host]transwarp> CREATE TABLE bucket_user_info(
                    > name STRING,
                    > acc_num STRING,
                    > password STRING,
                    > citizen_id STRING,
                    > bank_acc STRING,
                    > reg_date STRING,
                    > acc_level STRING)
                    > CLUSTERED BY (acc_num)
                    > INTO 3 BUCKETS;
    
    举例:多层分桶,桶内排序
    [$host]transwarp> CREATE TABLE bucket_user_info(
                    > name STRING,
                    > acc_num STRING,
                    > password STRING,
                    > citizen_id STRING,
                    > bank_acc STRING,
                    > reg_date STRING,
                    > acc_level STRING)
                    > CLUSTERED BY (acc_num, citizen_id)
                    > INTO 6 BUCKETS;
    
    桶内排序

    分桶表的数据写入

    向分桶表写入数据只能通过INSERT,而不能LOAD。为表分桶不会影响Inceptor如何向表写入数据,只会改变Inceptor从表读出数据的方式。所以在向分桶表中写入数据时,Inceptor不会自动按照建表时指定的分桶方式将数据写入不同桶中。 相较未分桶表,用户在分桶表中可以进行更高效的取样和一些其他的省时操作,比如map join。但是,Inceptor要等到对表进行写入时才会执行创建表时规定的分桶方式,所以表的元数据显示的表实行可能和表真实的形式不一样。我们应该避免这样的情况。下面我们看看如何正确地给表分桶并写入数据。
    举例:向分桶表写入数据
    首先,建表:
    [$host]transwarp> CREATE TABLE user_info_bucketed (
                    > name STRING,
                    > acc_num STRING,
                    > password STRING,
                    > citizen_id STRING,
                    > bank_acc STRING,
                    > reg_date STRING)
                    > PARTITIONED BY (acc_level STRING)
                    > CLUSTERED BY (acc_num) INTO 25 BUCKETS;
    
    我们在这里根据user_id分桶。现在我们写入数据:
    [$host]transwarp> set hive.enforce.bucketing = true;
    [$host]transwarp> FROM user_id
                    > INSERT OVERWRITE TABLE user_info_bucketed
                    > PARTITION (acc_level='A')
                    > SELECT name, acc_num, password, citizen_id, bank_acc, reg_date
                    >WHERE acc_level = 'A';
    

    set hive.enforce.bucketing = true指令让Inceptor自动根据表的分桶填入数据,写入时,Inceptor会尽量均匀地将数据哈希进各个桶中。