• Hive数据仓库笔记(二)


    分区和桶:

     

    分区:可以提高查询的效率,只扫描固定范围数据,不用全部扫描

    CREATE TABLE logs (ts BIGINT, lineSTRING) PARTITIONED BY (dt STRING, country STRING);

    通过关键字PARTITIONED BY 定义分区表

     

    LOAD DATA LOCAL INPATH '/home/data/file1'

    INTO TABLE logs

    PARTITION (dt='2001-01-01',country='GB');

    加载数据到分区表的时候,分区字段的值需要被明确指定。

     

    当在导入一些数据,可以看到Hive分区表的目录结构:

    /user/hive/warehouse/logs

    ├── dt=2001-01-01/

    │├── country=GB/

    ││ ├── file1

    ││ └── file2

    │└── country=US/

    │└── file3

    └── dt=2001-01-02/

    ├── country=GB/

    │└── file4

    └── country=US/

    ├── file5

    └── file6

     

    查看分区表的分区信息:

    hive> SHOW PARTITIONS logs;

    dt=2001-01-01/country=GB

    dt=2001-01-01/country=US

    dt=2001-01-02/country=GB

    dt=2001-01-02/country=US

     

    只查跟该分区相关的信息:

     

    SELECT ts, dt, line

    FROM logs

    WHERE country='GB';

     

    桶表:

    组织表或者分区表为桶表的两个原因:

    1.      提高查询效率针对Map  join      

    2.      使取样更高效

     

    创建桶表:

    CREATE TABLE bucketed_users (id INT,name STRING)

    CLUSTERED BY (id) INTO 4 BUCKETS;

    指明分桶的列和数量

     

    CREATE TABLE bucketed_users (id INT,name STRING)

    CLUSTERED BY (id) SORTED BY (id ASC)INTO 4 BUCKETS;

    排序使Map join更加高效

     

    创建users表

    CREATE TABLE users (id int, name String )

    ROW FORMAT DELIMITED

    FIELDS TERMINATED BY ' ';

    导入测试数据:

    LOAD DATA LOCAL INPATH '/home/data/users.txt'

    OVERWRITE INTO TABLE users ;

    为了hive识别创建表时定义的桶的数量设置 hive.enforce.bucketing属性为true.

    set hive.enforce.bucketing=true

    将users表的数据导入:

    INSERT OVERWRITE TABLE bucketed_users

    SELECT * FROM users

    通过hadoop dfs -ls /user/hive/warehouse/bucketed_users; 查看可以知道每个桶代表一个文件,4个桶就是4个文件。

    每个桶有一部分数据

    通过以下命令查看:

    hive> dfs -cat/user/hive/warehouse/bucketed_users/000000_0;

    0Nat

    4Ann

    TABLESAMPLE 取样数据 返回表的1/4

    hive> SELECT * FROM bucketed_users

    > TABLESAMPLE(BUCKET 1 OUT OF 4 ON id);

    4 Ann

    0 Nat

    返回表数据的1/2

    hive> SELECT * FROM bucketed_users

    > TABLESAMPLE(BUCKET 1 OUT OF 2 ON id);

    4 Ann

    0 Nat

    2 Joe

    如果对没有分桶的表进行取样,使用rand()函数,即使只是取样一部分数据,也会扫描整个数据集。

    hive> SELECT * FROM users

    > TABLESAMPLE(BUCKET 1 OUT OF 4 ONrand());

    2 Joe

    存储格式:

    默认的存储方式:Delimited text  分隔符是Ctrl-A

    因此CREATE TABLE ...;就相当于

    CREATE TABLE ...

    ROW FORMAT DELIMITED

    FIELDS TERMINATED BY '01'

    COLLECTION ITEMS TERMINATED BY '02'

    MAP KEYS TERMINATED BY '03'

    LINES TERMINATED BY ' '

    STORED AS TEXTFILE;

    Binary storage formats: Sequence files,Avro datafiles, Parquet files, RCFiles, and ORCFiles

    二进制格式分为:面向列的格式和面向行的格式

    面向列的格式处理表里列少的情况,面向行的格式处理单行里列比较多的情况。

    Hive支持的面向行的两种格式:Avrodatafiles、sequence files

    表被存储成Avro格式:

    SET hive.exec.compress.output=true;

    SET avro.output.codec=snappy;

    CREATE TABLE ... STORED AS AVRO;

    Hive支持的面向列的格式:Parquet,RCFile, and ORCFile

    创建一个副本表使用PARQUET格式:

    CREATE TABLE users_parquet STORED ASPARQUET

    AS

    SELECT * FROM users;

    自定义SerDe:RegexSerDe:

    使用自定义SerDe加载数据,SerDe需要使用正则表达式

    常用的正则表达式元字符:

    代码

    说明

    .

    匹配除换行符以外的任意字符

    w

    匹配字母或数字或下划线或汉字

    s

    匹配任意的空白符

    d

    匹配数字

    

    匹配单词的开始或结束

    ^

    匹配字符串的开始

    $

    匹配字符串的结束

    CREATE TABLE stations (usaf STRING, wbanSTRING, name STRING)

    ROW FORMAT SERDE'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'

    WITH SERDEPROPERTIES (

    "input.regex" = "(\d{6})(\d{5}) (.{29}) .*"

    );

    LOAD DATA LOCAL INPATH "/home/data/stations-fixed-width.txt"

    INTO TABLE stations;

    自定义SerDe 从文件里读固定宽度的位置的元信息,如果不是指定的宽度,该行记录为null。

    自定义SerDe效率不高。

    导数据:

    inserts:

    INSERT OVERWRITE TABLE target

    SELECT col1, col2

    FROM source;

    分区表:

    INSERT OVERWRITE TABLE target

    PARTITION (dt='2001-01-01')

    SELECT col1, col2

    FROM source;

    动态指定分区:

    INSERT OVERWRITE TABLE target

    PARTITION (dt)

    SELECT col1, col2, dt

    FROM source;

    Hive里可以把From放到前面:

    FROM source

    INSERT OVERWRITE TABLE target

    SELECT col1, col2;

    多表插入更加高效,源表只扫描一次可产生不同的输出。

    FROM records2

    INSERT OVERWRITE TABLE stations_by_year

    SELECT year, COUNT(DISTINCT station)

    GROUP BY year

    INSERT OVERWRITE TABLE records_by_year

    SELECT year, COUNT(1)

    GROUP BY year

    INSERT OVERWRITE TABLE good_records_by_year

    SELECT year, COUNT(1)

    WHERE temperature != 9999 AND quality IN(0, 1, 4, 5, 9)

    GROUP BY year;

    一个源表records,三个不同的表通过查询同一张表获得数据。

    CREATETABLE...AS SELECT:

    CREATE TABLE target

    AS

    SELECT col1, col2

    FROM source;

    更改表:

    重命名表名:

    ALTER TABLE source RENAME TO target;

    添加新的列:

    ALTER TABLE target ADD COLUMNS (col3STRING);

    由于hive不允许更新已经存在的记录数据,所以该方法一般的替代方案是重新创建新表CTAS。

    删除表:

    删除数据,对于外部表只删除元数据信息,数据遗留着。

    DROP TABLE my_table;

    删除所有数据但保存表的定义:

    TRUNCATE TABLE my_table;

    TRUNCATE不支持外部表,替代方案是dfs –rmr 直接删除外部表目录。

    如果创建一个新的空表跟另一个表有相同模式使用like 关键字:

    CREATE TABLE new_table LIKE existing_table;

    查询数据

    hive> FROM records2

    > SELECT year, temperature

    > DISTRIBUTE BY year

    > SORT BY year ASC, temperature DESC;

    1949 111

    1949 78

    1950 22

    1950 0

    1950 -11 

    每个ReducerSORT BY 后都会产生一个文件。

    DISTRIBUTE BY 控制给定年份的数据进入相同的reducer分区,如1950 年的进入相同Reducer分区

  • 相关阅读:
    【转】关于Oracle将小于1的数字to_char后丢掉0的解决办法
    【转】RadControls for Silverlight(学习2-RadDataPager)
    【转】RadControls for Silverlight(学习1-GridView)
    【转】 Easy RadControl 之 RadGridView(Silverlight)
    【转】silverlight telerik RadGridView 列头显示其他控件
    黑产江湖
    佳人篇
    联之道
    西二旗程序员家庭装修的架构之路
    西二旗程序员家庭装修的架构之路
  • 原文地址:https://www.cnblogs.com/bigdata1024/p/8387431.html
Copyright © 2020-2023  润新知