定位:
分布式通用SQL引擎:支持Hyperbase、Search、ArgoDB、StellarDB和Slipstream等核心数据库和计算引擎。逻辑数仓。
分布式关系型数仓:基于Hive和Spark,主要用于离线分析(对时间不敏感)。主要是关系型的数据。
数据类型是不一样的,要放在不同的数据库中。关系型数据放在HDFS中(Hive底层),半结构化数据放在Hyperbase(思维表)中,文本类型需要综合搜索防在Search(切词和全文索引),一体化的统一架构防在ArgoDB,图防在StellarDB中。
逻辑数仓:数据其实是分离的,但是在逻辑上是一个。
connector:为BI、ETL工具提供标准JDBC、ODBC接口。
SQL Compiler包括:SQL语法解析器、规则和代价优化器、代码生成器。
PL/SQL Compiler包括:存储过程解析器、控制流优化器、并行优化器。
Transaction Manager:分布式增删改、事务并发控制器。
Spark:星环发行版
计算资源:Executor是资源调度的基本单元。
存储各种类型的元数据,如Inceptor表、Hyperbase表、Search表、Slipstream流表等,数据存储在TxSQL(MySql引擎)上。
Client- CLI(命令行界面):Beeline
- JDBC/ODBC
- Web UI
- Waterdrop:Inceptor SQL IDE工具,支持主流的关系数据库和数据仓库,如Oracle、DB2、MySQL、Hive、Teradata、SAP等。
表下面分区,分区下面分桶。因为在大数据中,索引是不合适的,因为索引进行更新开销是非常大的,对数据进行分区。分区下面分桶,用于join连接。
数据库是一个包含若干表的命名空间和磁盘目录,类似于RDBMS中的数据库。系统会为每个数据库创建一个目录,目录名=数据库名.db,通常无法删除包含表的数据库,应该先删表,再删数据库。
table 表和关系型数据库一样,存储同一类关系的数据记录。
元数据存储在metastore中,表数据存储在HDFS、Hyperbase(用于半结构化)和Search(用于全文数据)中。
按照所有权分类,表可以分为内表和外表:
- 内表(Managed Table,又称托管表)
系统具有内表的完全控制权,负责管理它的生命周期,元数据存储在metastore中,想删就删。表数据默认存储在数据库(database)目录下的对应子目录(文件夹)中(目录名=表名),或者人工创建的外部目录中。删除内表时,会同时删除表数据,以及metastore中的元数据。 - 外表(External Table)
系统不具有外表的完全控制权,更加常用。元数据存储在metastore中,表数据通常存储在指定的外部存储目录中。删除外表时,不会删除表数据,但会删除metastore中的元数据。
按存储格式分类,表可以分为Text表和ORC表:
- Text表
系统默认的表类型,无压缩,行存储,仅支持批量Insert,性能较低,主要用于导入原始数据时建立过渡表(贴源层,靠近数据源,仅进行简单清洗)。 - ORC表
优化的列式存储,轻量级索引,压缩比高,仅支持批量Insert;是Inceptor计算的主要表类型,适用于数仓离线分析,通常由Text表生成(清洗转换后,通常为ORC表)。
按存储格式分类,分为ORC事务表、Hyperbase表以及ES表:
- ORC事务表:由ORC表衍生而来,继承了ORC表的所有特性,支持完整CURD以及分布式事务处理。多版本文件存储,定期做压缩,10~20%的性能损失。
- Hyperbase表:存储在Hyperbase上,支持多种索引,以及Insert、Update、Delete;适用于高并发点查(简单条件,精确查询),支持半结构化数据、小对象(10M以内的图片和音视频文件)存储。
- ES表
原始数据和索引数据都存储在ElasticSearch中,支持模糊、语义和全文检索,适用于综合搜索
一张表分成多个分区。因为在大数据(PB级)中,索引是不合适的,因为索引进行更新开销是非常大的。要把数据集合变小。
含义:将表按照某个或某几个字段(分区键)划分为更小的数据集。
作用:减少不必要的全表扫描,缩小查询范围,提升查询效率
存储:一个分区对应于表目录下的一个子目录,可以进行单值分区(分区键=value)或者范围分区(分区键=_less_than_value):
例如上图,采用state作为分区键,这样在数据库中,会有右边这个进行划分。这样在Select查询的时候,只需要遍历相应的区域即可,缩小查询范围。
注意:单值分区不能出现在表结构中,因为已经用这个划分文件了,再存储就产生了冗余。
分区键通常高频出现在Select … Where条件查询中,为了避免产生过多的子目录和小文件,只对离散字段进行分区,如日期、地域、民族等。需要提前对分区数量进行预估,尽量避免数据倾斜。
用于提升join的效率。
通过分桶键哈希取模 *** 作(key hashcode % N),将表或分区数据随机分发到N个桶中。桶数N一般为质数,方便桶数不同进行 *** 作。
哈希取模的作用:数据划分:随机分为N个桶;数据聚合:Key相同的数据在同一个桶中。
分桶可以:
- 提高Join查询效率:如果两个表的Join列都做了分桶,且分桶数相同或成倍数,那么相同列值的数据会分到编号相同或有对应关系的桶中,这样就不用全表遍历,对应的桶做Join就可以了;
- 提高取样效率:从桶中直接抽取数据。
假如有两张表,都分仨桶,那么每条数据都是在同一个桶号中的(即,第一条数据都在0桶,第4条数据都在1桶),这样做join是比较容易的。
存储时,在表或分区目录下,每个桶存储为一个文件,文件的大小应控制在100~200MB之间(ORC表压缩后)。如果桶文件小于HDFS Block, 那么一个桶对应一个Block,否则会存储在多个Block 中。
分桶用法:
- 先分区后分桶;
- 分桶键和分桶数在建表时确定,不允许更改,否则必须重新分桶;
- 分桶键必须出现在表结构中
数据进入数仓时,并不检查数据的规范性,而是查询时再验证。这样写入速度快,适合处理大规模数据。查询时处理尺度很宽松(弱校验),尽可能容忍各种错误。
Inceptor SQL SQL DDL 数据库 *** 作Create/Drop/Alter/Use/Describe/Show Database(s)
完整建表语句:
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [表 *** 作.] [( [COMMENT ' '] [, ...])] [COMMENT ''] [PARTITIonED BY [RANGE] ( [COMMENT ' '] [, ...])] [CLUSTERED BY ( [, ...]) [SORTED BY ( [ASC|DESC] [, [ASC|DESC]...])] INTO BUCKETS] [ [ROW FORMAT ] [STORED AS (TEXTFILE|ORC|CSVFILE)] | STORED BY ' ' [WITH SERDEPROPERTIES (<...>)] ] [LOCATION ' '] [TBLPROPERTIES (' '=' ', ...)];
Create/Drop/Alter/Truncate/Describe/Show Table(s)
创建内表
# 通过自定义Schema来创建内表 CREATE TABLE [([, ...])]; # 通过已存在的表或视图来创建内表,只复制Schema,不复制数据 CREATE TABLE LIKE ; # 通过查询结果来创建内表,既复制Schema,又复制数据 CREATE TABLE AS SELECT ;
高级 *** 作:
分区和分桶
单值分区:一个分区对应分区键的一个值,目录名为“分区键=键值”
分区键不能和表结构中的列重复,因为分区键和数据已存储在分区目录名中,否则会造成数据冗余。
CREATE [EXTERNAL] TABLE ([, ...]) PARTITIonED BY ( , ...) [CLUSTERED BY ...] [ROW FORMAT ] [STORED AS TEXTFILE|ORC|CSVFILE] [LOCATION ' '] [TBLPROPERTIES (' '=' ', ...)];
在create语句之后,是不会创建文件的,因为还不知道是动态还是静态分区,系统只是知道你创建了分区。
单值分区分为两类:
- 单值静态分区
# 单值静态分区导入时系统没有任何机制来保证数据导入的正确性,只有靠用户自己 INSERT OVERWRITE TABLE PARTITION (= [, = , ...]) SELECT ; INSERT INTO TABLE PARTITION ( = [, = , ...]) SELECT ; LOAD DATA [LOCAL] INPATH ' ’ [OVERWRITE] INTO TABLE PARTITION ( = [, = , ...]);
- 单值动态分区:导入数据时,系统可以动态判断目标分区
自动设置分区,需要进行设置。动态定义必须写在静态之后。
set hive.exec.dynamic.partition=true; set hive.exec.max.dynamic.partitions=2000; INSERT (OVERWRITE | INTO) TABLE PARTITION ([= , ..., ] , [..., ]) SELECT ;
新增、删除、重命名和清空分区:
ALTER TABLE ADD PARTITION (= ); ALTER TABLE DROP PARTITION ( = ); ALTER TABLE PARTITION ( = ) RENAME TO PARTITION ( = ); TRUNCATE TABLE PARTITION ( = );
范围分区
每个分区对应分区键的一个区间,凡是落在指定区间内的数据都被存储在对应的分区下。
创建范围分区:
CREATE [EXTERNAL] TABLE (, , ...) PARTITIonED BY RANGE ( , ...) (PARTITION [ ] VALUES LESS THAN ( ), [PARTITION [ ] VALUES LESS THAN ( ), ... ] PARTITION [ ] VALUES LESS THAN ( |MAXVALUE) ) [ROW FORMAT ] [STORED AS TEXTFILE|ORC|CSVFILE] [LOCATION ' '] [TBLPROPERTIES (' '=' ', ...)];
范围分区需手工指定,可在建表时添加分区,也可建表后通过Alter Table添加或删除分区
分桶按分桶键哈希取模的方式,将表中数据随机分发到若干桶文件中。
创建分桶表:INTO BUCKETS设定桶的数量,SORTED BY设定桶内排序,默认升序
CREATE [EXTERNAL] TABLE ([, ...])] [PARTITIonED BY ...] CLUSTERED BY ( ) [SORTED BY ( [ASC|DESC] [, [ASC|DESC]...])] INTO BUCKETS [ROW FORMAT ] [STORED AS TEXTFILE|ORC|CSVFILE] [LOCATION ' '] [TBLPROPERTIES (' '=' ', ...)];
写入分桶表
set hive.enforce.bucketing = true; set mapreduce.job.reduces=4; INSERT (OVERWRITE | INTO) TABLE SELECT, , ... FROM DISTRIBUTE BY SORT BY [ASC|DESC] [, col_name [ASC|DESC], ...] [CLUSTER BY ]
与分区键不同,分桶键必须是表结构中的列。分桶键和分桶数在建表时确定,不允许更改。
SQL DML数据预处理:文件编码为UTF-8,n为换行符
导入Load导入
将文件中的数据导入已存在的表或分区。仅将数据文件移动到表或分区的目录中,不会对数据进行任何处理,如分桶、排序。不支持动态分区导入。
不推荐使用Load导入数据:在安全模式下的权限设置步骤较多。
#是文件存储路径,如果标注LOCAL,指向本地磁盘路径,不标则指向HDFS路径 LOAD DATA [LOCAL] INPATH ' ’ [OVERWRITE] INTO TABLE [PARTITION ( = , ...)];
Insert导入
# 单值静态分区导入 INSERT (OVERWRITE | INTO) TABLE PARTITION (查询= [, = , ...]) SELECt ; # 单值动态分区导入 set hive.exec.dynamic.partition=true; set hive.exec.max.dynamic.partitions=2000; INSERT (OVERWRITE | INTO) TABLE PARTITION ([ = , ..., ] , [..., ]) SELECT ;
分桶与聚合:
Distribute By:将Distribute By列值相同的数据发送给同一个Reduce任务,实现数据按指定列聚合
%type属性
基于变量或数据库表的列定义一个变量。该变量的类型与被参照变量或列的类型相同;当被参照变量的类型改变之后,新定义变量的类型也会随之改变
%rowtype属性
基于数据库表定义一个记录型变量。该变量的字段名和字段类型就是被参照表的字段名和字段类型;当被参照表的结构发生变化时,新定义变量也会发生改变
标量类型
用于保存单个值,Inceptor支持的标量类型有Int、String、Double、Boolean等
复合类型
如Record、Collection等
DECLARE transid STRING BEGIN SELECT trans_id into transid from transactions where acc_num=6513065 DBMS_OUTPUT.put_line(transid) EXCEPTION --WHEN too_many_rows THEN DBMS_OUTPUT.put_line ('too many rows') END;
存储过程
CREATE OR REPLACE PROCEDURE hello_world() IS DECLARE l_message STRING := 'Hello World!' BEGIN DBMS_OUTPUT.put_line (l_message) END; BEGIN hello_world() END;复习
如何定位Inceptor?它与Hive有什么区别?
如何理解Inceptor读时模式。
分区的目的是什么?分区有几种类型?如何将数据导入分区表?
分桶的目的是什么?如何将数据导入分桶表?
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)