1)数据库是面向事务设计,数据仓库是面向主题设计的;
2)数据库一般存储了业务数据,数据仓库一般存储的是历史数据;
3)数据库设计应该尽量避免冗余,一般针对某一业务应用进行设计;数据仓库在设计时会有意地引入冗余,依照分析需求、分析维度、分析指标进行设计;
4)数据库是为了捕获数据而设计,数据仓库是为了分析数据而设计;
数据仓库是在数据库已经大量存在的情况下,为了进一步挖掘数据资源,以供数据用户决策使用而产生的。
从架构图看出,最下层是数据源,数据仓库中的数据一般来源于不同的数据源,它可以是文档文件,也可以是数据库。中间层是我们的数据仓库,最上层是数据应用层。可以看出,数据是自下而上地流入数据仓库后,为上层应用提供数据的支持。可以这样理解,数据仓库只是一个中间集成化数据管理的平台。
数据仓库从各数据源获取数据,以及在数据仓库内的数据转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程。ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。
元数据主要记录了数据仓库中模型的定义、各层级之间的映射关系,监控数据仓库的数据状态,以及ETL的任务运行状态等。一般会通过元数据资料库进行统一存储和管理。
元数据是数据仓库管理系统的重要组成部分,元数据管理贯穿数据仓库构建的整个过程,直接影响着数据仓库的构建、使用和维护。
它的主要作用:
由此可见,元数据不仅定义了数据仓库中数据的模式、来源、抽取和转换规则等,而且是整个数据仓库系统运行的基础,元数据把数据仓库系统中各个松散的组件联系起来,组成了一个有机的整体。
Hive是基于Hadoop的一个数据仓库工具,主要用于数据的提取、转换、加载。Hive能够将结构化数据文件映射成一张数据表,并提供SQL查询功能,能将SQL语句转化成MapReduce任务进行运算,底层由HDFS来提供数据的存储。
Hive | RDBMS | |
---|---|---|
查询语言 | HQL | SQL |
数据存储 | HDFS | Raw Device or Local FS |
执行 | MapReduce | Executor |
数据延迟 | 高 | 低 |
数据规模 | 大 | 小 |
应用场景 | 数据统计分析 | 数据持久化存储 |
cd /export/softwares/
tar -zxvf apache-hive-3.1.0-bin.tar.gz -C ../servers/
cd /export/servers/apache-hive-3.1.0-bin/conf
cp hive-env.sh.template hive-env.sh
# 配置HADOOP_HOME
HADOOP_HOME=/export/servers/hadoop-3.1.1
# Hive配置文件路径
export HIVE_CONF_DIR=/export/servers/apache-hive-3.1.0-bin/conf
hive-site.xml:
cd /export/servers/apache-hive-3.1.0-bin/conf
vim hive-site.xml
配置文件内容:
<configuration>
<property>
<name>javax.jdo.option.ConnectionUserNamename>
<value>rootvalue>
property>
<property>
<name>javax.jdo.option.ConnectionPasswordname>
<value>123456value>
property>
<property>
<name>javax.jdo.option.ConnectionURLname>
<value>jdbc:mysql://node03:3306/hive?createDatabaseIfNotExist=true&useSSL=falsevalue>
property>
<property>
<name>javax.jdo.option.ConnectionDriverNamename>
<value>com.mysql.jdbc.Drivervalue>
property>
<property>
<name>hive.metastore.schema.verificationname>
<value>falsevalue>
property>
<property>
<name>datanucleus.schema.autoCreateAllname>
<value>truevalue>
property>
<property>
<name>hive.server2.thrift.bind.hostname>
<value>node03.hadoop.comvalue>
property>
configuration>
# 修改配置文件
sudo vim /etc/profile
export HIVE_HOME=/export/servers/apache-hive-3.1.0-bin
export PATH=:$HIVE_HOME/bin:$PATH
# 安装mysql相关包
yum install mariadb mariadb-server
# 启动mysql服务
systemctl start mariadb
# 设置用户名和密码
mysql_secure_installation
# 给用户授权
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;
flush privileges;
create database [if not exists] 数据库名;
create database 数据库名 location 存储路径;
例如:
create database myhive location '/myhive';
hive默认存储位置由hive-site.xmlp配置文件的hive.metastore.warehouse.dir
参数来指定。
hive只能修改数据库的一些基本属性,不能够修改元数据信息(比如数据库名称、数据库所在位置等)。
alter database 数据库名 set dbproperties('参数名'='属性值');
desc database [extended] 数据库名;
如果指定了extended参数,那么就会显示数据库的详细信息。
drop database 数据库名 [cascade];
如果数据库不为空,那么需要指定cascade参数。
创建表的基本语法:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...)
[SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
SerDe是Serialize和Deserilize的英文缩写。hive通过序列化和反序列化来完成表的读写操作。序列化操作就是把hive使用的java对象转换成能写入hdfs的字节序列,或者其他系统能识别的流文件。反序列化操作就是把字符串或者二进制流转换成hive能识别的java对象。比如:select语句会用到Serialize对象, 把hdfs数据解析出来;insert语句会使用Deserilize,数据写入hdfs系统,需要把数据序列化。
STORED AS TEXTFILE
;如果数据需要压缩,使用STORED AS SEQUENCEFILE
。hive默认的文件存储格式为TEXTFILE
,可以通过配置 hive.default.fileformat
来修改;类型 | 描述 | 示例 | 版本限制 |
---|---|---|---|
BOOLEAN | true/false | 1Y | |
TINYINT | 1个字节的有符号整数,-128~127 | 1S | |
SMALLINT | 2个字节的有符号整数,-32768~32767 | 1S | |
INT | 4个字节的有符号整数 | 1 | |
BIGINT | 8个字节的有符号整数 | 1L | |
FLOAT | 4个字节的单精度浮点数 | 1.0 | |
DOUBLE | 8个字节的双精度浮点数 | 1.0 | Hive 2.2.0+ |
DECIMAL | 任意精度的有符号小数 | 1.0 | Hive 0.11.0+开始引入38位小数,Hive0.13.0+开始可以自定义小数位 |
Numeric | 任意精度的有符号小数 | 1.0 | Hive 3.0.0+ |
STRING | 变长字符串 | "a"或’a’ | |
VARCHAR | 变长字符串 | "a"或’a’ | Hive 0.12.0+ |
CHAR | 定长字符串 | "a"或’a’ | Hive 0.13.0+ |
BINARY | 字节数组 | Hive 0.8.0+ | |
TIMESTAMP | 时间戳,毫秒为单位 | 1287897987312 | Hive 0.8.0+ |
DATE | 日期 | ‘2020-06-06’ | Hive 0.12.0+ |
INTERVAL | 时间频率间隔 | Hive 1.2.0+ | |
ARRAY | 数组,只能存储相同类型的数据 | array(1,2,3,4,5) | Hive 0.14+ |
MAP | 存储键值对的集合 | map(‘a’,1,‘b’,2) | Hive 0.14+ |
STRUCT | 结构体,可存储不同类型的数据 | person_struct(1, ‘小白’, 18) | |
UNION | 有限取值范围内的一个值 | hive 0.7.0+ |
具体类型可以参考:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
use myhive;
# 创建简单表
create table company(id int, name string);
# 创建表并指定分隔符
create table if not exists company (id, name)
row format delimited fields terminated by '\t';
# 根据查询结果创建表
create table t2 as select * from t1; # 复制表结构和数据
create table t2 like t1; # 复制表结构
当表中的数据量非常大的时候,我们可以对一个表的数据进行分区,例如:日期。这样可以提高对数据的查询效率。
# 创建分区表
create table score(s_id string,c_id string, s_score int) partitioned by (year string, month string) row format delimited fields terminated by '\t' location '/score';
上面我们创建了一个分区表score,它按照字段year和month进行分区。month值相同的数据会存放在同一个分区里面。
这里需要强调的是,分区列year和month并不真正存在于数据库表中,它们只是我们人为规定的。Hive不支持将表中的某些列作为分区列。
hdfs dfs -ls /score/year=2020&month=6/
show partitions score;
load data local inpath '/export/data/score.csv' into table score partition (year='2020',month='6');
select * from score where year = '2020' and month = '6';
查询分区数据的方式指定分区字段作为查询条件。指定分区名之后就不再全表扫描,直接从指定分区中查询,从而提高数据的查询效率。
alter table score add partition(year='2020', month='5');
alter table score drop partition(year='2020', month='5');
与分区不同的是,分区依据的不是表里面真实的列,而分桶是依据表里面真实的列,将数据按照指定的字段分到不同的桶里面。
Hive是通过对某列值的hash对分桶数取模来决定数据存放在哪个桶。比如说对name属性分为3个桶,那么就是对name属性值的hash对3进行取模,然后按照取模结果对数据分桶存放。如果结果为0则记录在第一个文件,结果为1记录在第二个文件,结果为2记录在第三个文件,以此类推。
如果要使用分桶功能,首先要先开启分桶:
set hive.enforce.bucketing=true;
然后设置Reduce的个数:
set mapreduce.job.reduces = 3;
创建表时候,指定分桶的数量:
# 创建表时指定按照c_id列进行分桶,并且将数据放入到3个分桶中
create table ... clustered by(c_id) into 3 buckets row format delimited fields terminated by '\t';
向分桶表插入数据:
insert overwrite table course select * from course_two cluster by (c_id);
查看分桶数据:
# 查看第一个分桶的数据
select * from course tablesample(bucket 1 out of 3 on c_id);
# 重命名
alter table old_table_name rename to new_table_name;
# 查询表结构
desc tablename;
# 添加列
alter table tablename add columns (column_name column_type, ...);
# 删除表
drop table tablename;