本文将带领你进入Hadoop的生态世界,本文为Hadoop生态从0到1_理论篇(7日连载),后期会推出Hadoop生态从0到1_实践篇(7日连载)
Hadoop系统整体架构V2
Hive - SQL/MR编译器
Pig - Pig-Latin/MR编译器
Zookeeper - 分布式协同调度和锁
Avro - 接口开发工具
HBase - 基于列簇的分布式
NoSQLFlume/NG/Scribe - 日志流汇总工具
Mahout - 基于MR的算法库
Drill/Impala - 内存SQL引擎,Dremel开源实现
Thrift - 接口开发工具
Sqoop - ETL工具
Oozie - 工作流
Doug Cutting(一位大牛)主导的Apache Nutch项目是Hadoop软件的源头,该项目始于2002年,是Apache Lucene 的子项目之一。
Google在2003年于SOSP上发表了分布式文件系统的论文“The Google File System”–> 2004年,Nutch的分布式文件系统(NDFS)开始开发。
2004年,Google在OSDI上发表了题为“MapReduce: Simplified Data Processing on Large Clusters”的论文 --> Doug Cutting等人开始实现MapReduce计算框架并与NDFS(Nutch Distributed File System)结合起来,共同支持Nutch的主要算法。
2006年,它逐渐成为一套完整而独立的软件,已经到Yahoo!工作的Doug Cutting将这套大数据处理软件命名为Hadoop。
2008年初,Hadoop成为Apache的顶级项目,除Yahoo!之外在众多互联网企业中得到应用。此时的Hadoop系统又称为Hadoop v1,主要由两个核心组件构成:HDFS和MapReduce。
一些围绕在Hadoop周围的开源项目,为完善大数据处理的全生命周期提供了必要的配套和补充。这些软件常用的有ZooKeeper、Hive、Pig、HBase、Storm、Kafka、Flume、Sqoop、Oozie、Mahout等。
2012年5月,Hadoop v2的alpha版本发布,其中最重要的变化是在Hadoop核心组件中增加了YARN(Yet Another Resource Negotiator)。YARN的出现是为了把计算框架与资源管理彻底分离开,解决Hadoop v1由此带来的扩展性差、单点故障和不能同时支持多种计算框架的问题。YARN对标的恰好就是Google的Borg系统。至此,Hadoop方才能够与Google的大数据平台比肩。
Hadoop也成为自Linux以来最成功的开源软件,没有之一。
2013年出现了Spark,在全面兼容Hadoop原有组件的基础上,Spark通过更多的利用内存处理大幅提高系统性能。
配置文件均为空,Hadoop完全运行在本地
此时的Hadoop系统仅仅是一个独立的Java进程
不需要与其他节点交互,单机模式就不使用HDFS,也不加载任何其他Hadoop的守护进程
该模式主要用于开发调试MapReduce程序的应用逻辑
在“单节点集群”上运行Hadoop,其中所有的守护进程都运行在同一台机器上。
该模式在单机模式之上增加了代码调试功能,允许你检查内存使用情况,HDFS输入输出,以及其他的守护进程交互。
Hadoop系统中的所有守护进程分别运行在一个集群中的不同机器上。
几个重要的配置文件:
core-site.xml 配置HDFS节点名称和地址
hdfs-site.xml 配置HDFS存储目录,复制数量
mapred-site.xml 配置mapreduce的jobtracker地址
⚠️jobtracker是Hadoop1.0时的叫法,SourceManager是Hadoop2.0的叫法。
⚠️jobtracker&SourceManager 均为MapReduce中的组件。
1.直接启动或者关闭所有的进程(不推荐,由于分布式下,namenode和datanode分布在不同机器上,启动的进程不相同)
在启动hadoop进程的时候我们通常都是直接使用(默认hadoop根目录下)
> sbin/start-all.sh
> sbin/stop-all.sh
但是有时候直接启动进程并不完整,我们就需要使用单独的命令
2.分模块启动(推荐)
2.1.启动和关闭 namenode,secondaryNamenode和datenode (启动hdfs)
> sbin/start-dfs.sh sbin/stop-dfs.sh
2.2启动yarn
> sbin/start-yarn.sh sbin/stop-yarn.sh
3.各个节点单独启动
1. 单独启动namenode守护进程
sbin/hadoop-daemons.sh start namenode
2. 单独启动DataNode守护进程
sbin/hadoop-daemons.sh start datanode
3. 单独启动SecondaryNameNode 守护进程
sbin/hadoop-daemons.sh start SecondaryNameNode
4.开启resourcemanager
sbin/yarn-daemon.sh start resourcemanager
5.开启nodemanager
sbin/yarn-daemons.sh start nodemanager
6.启动historyserver
sbin/mr-historyserver-dameon.sh start /stop historyserver
首先放一张简易但清晰的图表明HDFS在Hadoop系统的位置
Hadoop Distributed File System
Hadoop Distributed File System (HDFS) is the primary storage system used by Hadoop applications.
HDFS creates multiple replicas of data blocks and distributes them on compute nodes throughout a cluster to enable reliable, extremely rapid computations.
HDFS为了做到可靠性(reliability)创建了多份数据块(data blocks)的复制(replicas),并将它们放置在服务器群的计算节点中(compute nodes),MapReduce就可以在它们所在的节点上处理这些数据了。
存储并管理PB级数据
处理非结构化数据
注重数据处理的吞吐量(latency不敏感)
write-once-read-many存取模式
任何一个节点失效,不影响HDFS服务
HDFS可以自动完成副本的复制
存储小文件 (不建议使用)
大量的随机读 (不建议使用)
需要对文件的修改 (不支持)
文件切分成块(默认大小64M(Hadoop1) )(默认大小128M(Hadoop2)),以块(block)为单位,每个块有多个副本存储在不同的机器(node)上,副本数可在文件生成时指定(默认3)。
NameNode是主节点,存储文件的元数据如文件名,文件目录结构,文件属性(生成时间,副本数,文件权限),以及每个文件的块列表以及块所在的DataNode等等
DataNode在本地文件系统存储文件块数据,以及块数据的校验和
可以创建、删除、移动或重命名文件,当文件创建、写入和关闭之后不能修改文件内容。
Namenode是一个中心服务器,单一节点(简化系统的设计和实现),负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。
文件操作,NameNode负责文件元数据的操作,DataNode负责处理文件内容的读写请求,跟文件内容相关的数据流不经过NameNode,只会询问它跟那个DataNode联系,否则NameNode会成为系统的瓶颈
⚠️NameNode 一般情况是独立存在于一个物理机中
副本存放在那些DataNode上由NameNode来控制,根据全局情况做出块放置决定,读取文件时NameNode尽量让用户先读取最近的副本,降低带块消耗和读取时延
Namenode全权管理数据块的复制,它周期性地从集群中的每个Datanode接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该Datanode节点工作正常。块状态报告包含了该Datanode上所有数据块的列表。
一个数据块在DataNode以文件存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。
心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode 的心跳,则认为该节点不可用。
集群运行中可以安全加入和退出一些机器
Secondary Namenode可以理解成是NameNode的一个热备(备份)
在文件创立时,每个数据块都产生校验和
校验和保存在.meta文件内
客户端获取数据时可以检查校验和是否相同,从而发现数据块是否损坏
如果正在读取的数据块损坏,则可以继续读取其它副本
删除文件时,其实是放入回收站/trash
回收站里的文件可以快速恢复
可以设置一个时间阈值,当回收站里文件的存放时间超过这个阈值,就被彻底删除,并且释放占用的数据块
☑️shell如果有回收站,会首先放入回收站,然而java代码默认可不放入
回收站配置(每个节点)
java代码
1)所谓HA(high available),即高可用(7*24小时不中断服务)。
2)实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA
机制:HDFS的HA和YARN的HA。
3)Hadoop2.0之前,在HDFS集群中NameNode存在单点故障(SPOF)。
4)NameNode主要在以下两个方面影响HDFS集群
NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启
NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用
HDFS HA有 手动切换|自动切换
详细讲解 https://edu.csdn.net/course/play/1409/22250
HDFS HA功能通过配置Active/Standby两个nameNodes实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器。
package hdfs;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
import org.apache.jasper.tagplugins.jstl.core.ForEach;
import com.cedarsoftware.util.IOUtilities;
public class app1 {
public static void main(String[] args) throws IOException, URISyntaxException {
FileSystem fileSystem = FileSystem.get(new URI("hdfs://icaa:9000"), new Configuration()); // fileSystem抽象类
System.out.println("fileSystem -> "+ fileSystem); //其实这里是fileSystem.toString
System.out.println("fileSystem.getClass -> "+ fileSystem.getClass());
/*
*
* 创建文件夹
*
* */
// 创建文件夹mkdir
fileSystem.mkdirs(new Path("/dir1"));
// 创建文件夹mkdir (多用户)
fileSystem.mkdirs(new Path("mydir"));
// 创建文件夹mkdir (两个参数->位置,参数)
fileSystem.mkdirs(new Path("/dir2"), new FsPermission("111"));
/*
*
* 上传文件
*
* */
// FSDatainputStream 输入流
FileInputStream in1 = new FileInputStream("/root/Downloads/hello");
// 上传文件creat
// FSDataOutputStream 输出流
// replication副本 // 这里数字单位:字节 //command➕1 是创建变量的快捷键
// 我写的这个是自定义话比较强的, 如果想用默认,则可使用fileSystem.create(new Path(""));
FSDataOutputStream out1 = fileSystem.create(new Path("/dir1/file1"), true, 1024000, (short)2, 1048576);
// 从in进入后 利用IOUtils 进行类似while的工作 给到out
IOUtils.copyBytes(in1, out1, 1024, true);
/*
* 换一种方法 // Progressable 表示进程 想看到进程
* */
final AtomicInteger writeBytes = new AtomicInteger(0); //writeBytes来看看进程 =进度条
FSDataOutputStream out2 = fileSystem.create(new Path("/dir1/file2"), new Progressable() {
// Progressable 表示进程
@Override
public void progress() {
// TODO Auto-generated method stub
System.out.println("writeBytes -> "+ writeBytes.get());
}
});
FileInputStream in2 = new FileInputStream("/root/Downloads/hello");
byte[] buffer = new byte[4];
int readBytes = in2.read(buffer);
while(readBytes!=-1) {
out2.write(buffer);
out2.flush();
out2.hsync();
writeBytes.addAndGet(readBytes);
readBytes = in2.read(buffer);
}
/*
*
* 读取数据
*
* */
FSDataInputStream in = fileSystem.open(new Path("/dir1/file1"));
IOUtils.copyBytes(in, System.out, 1024, true);
/*
*
* 查看数据分布也就在那个结点上 用到了 遍历
*
* */
// 遍历
FileStatus[] listStatus = fileSystem.listStatus(new Path("/"));
for(FileStatus fileStatus:listStatus) {
System.out.println(fileStatus);
}
// 查看数据分布结点
FileStatus[] listStatus2 = fileSystem.listStatus(new Path("/"));
for(FileStatus fileStatus:listStatus2) {
System.out.println(fileStatus);
if (!fileStatus.isDirectory()) {
BlockLocation[] fileBlockLocations = fileSystem.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());
for(BlockLocation blockLocation:fileBlockLocations) {
String[] hosts = blockLocation.getHosts();
for (String hostname : hosts) {
System.out.println("HOST NAME -> "+ hostname);
}
}
}
}
/*
*
* 其他
*
* */
// 遍历
FileStatus[] listStatus3 = fileSystem.listStatus(new Path("/"));
for(FileStatus fileStatus:listStatus3) {
System.out.println(fileStatus);
}
// 删除
//fileSystem.delete(arg0, arg1); 没有举例
//获取工作目录
//fileSystem.getWorkingDirectory().toString(); 没有举例
}
}
更多关于HDFS
https://blog.csdn.net/penggougoude/article/details/82357005
YARN 是怎么来的呢?那首先得从Hadoop1.0的缺陷说起
单点故障:MR的JobTracker和HDFS的NameNode两个核心服务均存在单点问题
模型单一:只能用MapReduce处理数据,迭代计算、图计算同样有大数据的处理场景。MR本质上是面向批处理的,并不支持实时或接近实时的处理请求。
低可拓展性:雅虎的Hadoop集群不超过4000个节点。
服务器利用率:JobTracker将管理集群视为很多的Map/Reduce槽(slot),然而在MR用运行的时候,大多数时候都是reduce槽在等待map槽完成(map 100% reduce 0%)。
使用灵活性:部分升级,全部需要升级。
Hadoop 2.0:由HDFS、MapReduce和YARN三个组建构成;
MapReduce:运行在YARN上的MR
YARN(Yet Another Resource Negotiator):资源管理系统
整个集群只有一个 , 负责集群资源的统一管理和调度
详细功能:
处理客户端请求
启动/ 监控ApplicationMaster
监控NodeManager
资源分配与调度
整个集群有多个 ,负责单节点资源管理和使用
详细功能:
单个节点上的资源管理和任务管理
处理来自ResourceManager 的命令
处理来自ApplicationMaster 的命令
每个应用有一个 , 负责应用程序的管理
详细功能:
数据切分
为应用程序申请资源 , 并进一步分配给内部任务
任务监控与容错
对任务运行环境的抽象
描述一系列信息
任务运行资源(节点 、 内存 、CPU )
任务启动命令
任务运行环境
ResourceManager
存在单点故障
正在基于ZooKeeper 实现HA
NodeManager
失败后 ,RM 将失败任务告诉对应的AM
AM 决定如何处理失败的任务
ApplicationMaster
失败后 , 由RM 负责重启
AM 需处理内部任务的容错问题
RMAppMaster 会保存已经运行完成的Task , 重启后无需重新运行
多类型资源调度
采用DRF算法(论文:“Dominant Resource Fairness: Fair Allocation of Multiple Resource Types”)
目前支持CPU和内存两种资源
多种资源调度器
FIFO
Fair Scheduler
Capacity Scheduler
多租户资源调度器
支持资源按比例分配
支持层级队列划分方式
支持资源抢占
YARN命令是hadoop中调用bin/yarn脚本文件,如果运行yarn脚本没有带任何参数,则会打印yarn所有命令的描述。
使用: yarn [–config confdir] COMMAND [–loglevel loglevel] [GENERIC_OPTIONS] [COMMAND_OPTIONS]
YARN有一个参数解析框架,采用解析泛型参数以及运行类。
表A:
详细说明请参考:Hadoop yarn 指令相关参数详解
https://blog.csdn.net/u010003835/article/details/83347589
MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)“和"Reduce(归约)”
☘️MapReduce篇幅过长,会单开一个专题
☘️故在此不多叙述
数据仓库简介
数据仓库本质上就是一个数据库。可以利用数据仓库来保存数据。数据仓库用于支持企业和组织的决策分析处理。数据仓库区别于传统的数据库,从下面几点说明。
Hive是基于Hadoop HDFS之上的数据仓库。我们可以把数据存储在这个基于数据的仓库之中,进行分析和处理,完成业务逻辑。
使用类sql来读、写、管理驻留在分布式存储系统的大型数据集。可以使用命令行工具和驱动连接到hive上。
Hive不是关系数据库,不适合实时查询和更新操作,不适合OLTP。
Hive在数据库中存放schema,数据存放在hdfs文件中,数据库和表都是路径。提供类sql语言(Hive ql,hql)。
Hive安装
1、下载安装介质
apache-hive-2.1.1-bin.tar.gz
2、安装hive(安装jdk、hadoop)
上传hive到ubuntu
$>tar -xzvf apache-hive-2.1.1-bin.tar.gz
$>mv apache-hive-2.1.1-bin /soft/
$>cd /soft
$>ln -s apache-hive-2.1.1-bin/ hive
$>sudo vi /etc/environment
HIVE_HOME=/soft/hive
PATH=...:/soft/hive/bin
$>source /etc/environment
$>hive --version
HADOOP_HOME环境变量配置
编辑[/soft/hive/conf/hive-env.sh],在文件末尾加上HADOOP_HOME环境变量
$>cd /soft/hive/conf
$>cp hive-env.sh.template hive-env.sh
$>vi hive-env.sh
加入如下内容:
HADOOP_HOME=/soft/hadoop
配置Hive的元数据库
hive使用rdbms存储元数据,内置了derby数据库
创建[/soft/hive/conf/hive-site.xml]文件
$>cp hive-default.xml.template hive-site.xml
替换${system:java.io.tmpdir}=/home/hadoop/hive
替换${system:user.name}=hadoop
进入Hive命令行界面
1、启动hadoop(最少启动一个datanode)
$>start-all.sh
2、初始化schema库
$>/soft/hive/bin/schematool -initSchema -dbType derby
3、进入hive shell
$>hive
这里如果我们输入 show databases; 则报错♂️
解决办法:hive --service metastore
原因:没有开启 metastore,需要先启动hive的metastore服务才行
建库删库
$>hive>show databases;
$>hive>show tables;
$>hive>create database myhive;
$>hive>use myhive;
$>hive>create table test(id int,name String);
$>hive>create table if not exists myhive.employee(eid int, name String, salary String, destination String) COMMENT 'Employee details' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;
$>hive>drop database myhive;
导入数据
1、准备employee.txt数据,内容如下
1201 gxf 4500 Techinical manager
1202 gxf1 4501 Techinical manager
2、导入数据
Hive支持插入,不支持删除和更新,加载数据到hive(hdfs)语法(LOAD DATA INPATH 'filepath' into TABLE TABLENAME)
$>hive>load data local inpath '/home/hadoop/Desktop/employee.txt' into table employee;
$>hive>!clear; //hive中执行shell命令
$>hive>dfs -lsr /; //hive中执行hdfs命令
$>hive>create table myhive.employee2 as select * from myhive.employee;//复制表(触发MP)
连接MYSQL: mysql -h localhost -u root -p
格式: mysql -h主机地址 -u用户名 -p用户密码
1、例1:连接到本机上的MYSQL
找到mysql的安装目录,一般可以直接键入命令mysql -u root -p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中
了,MYSQL的提示符是:mysql>
2、连接到远程主机上的MYSQL
假设远程主机的IP为:10.0.0.1,用户名为root,密码为123。则键入以下命令:
mysql -h10.0.0.1 -uroot -p123
(注:u与root可以不用加空格,其它也一样)
3、手动查询端口号
mysql> show global variables like ‘port’;
4、退出MYSQL命令
exit; (回车)
------------------------mysql基础知识提示------------------------
第一招、mysql服务的启动和停止
net stop mysql
net start mysql
第二招、登陆mysql
语法如下: mysql -u用户名-p用户密码
键入命令mysql -uroot -p,回车后提示你输入密码,输入12345,然后回车即可进入到mysql中了,mysql的提示符是:
mysql>
注意,如果是连接到另外的机器上,则需要加入一个参数-h机器IP
第三招、增加新用户
格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by "密码"
如,增加一个用户user1密码为password1,让其可以在本机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入mysql,然后键入以下命令:
grant select,insert,update,delete on *.* touser1@localhost Identified by "password1";
如果希望该用户能够在任何机器上登陆mysql,则将localhost改为"%"。
如果你不想user1有密码,可以再打一个命令将密码去掉。
grant select,insert,update,delete on mydb.* touser1@localhost identified by"";
第四招: 操作数据库
登录到mysql中,然后在mysql的提示符下运行下列命令,每个命令以分号结束。
1、 显示数据库列表。
show databases;
缺省有两个数据库:mysql和test。mysql库存放着mysql的系统和用户权限信息,我们改密码和新增用户,实际上就是对这个库进行操作。
2、 显示库中的数据表:
use mysql;
show tables;
3、 显示数据表的结构:
describe 表名;
4、 建库与删库:
create database 库名;
drop database 库名;
5、 建表:
use 库名;
create table 表名(字段列表);
drop table 表名;
6、 清空表中记录:
delete from 表名;
7、 显示表中的记录:
select * from 表名;
第五招、导出和导入数据
1. 导出数据:
mysqldump --opt test > mysql.test
即将数据库test数据库导出到mysql.test文件,后者是一个文本文件
如:mysqldump -u root -p123456 --databases dbname >mysql.dbname
就是把数据库dbname导出到文件mysql.dbname中。
2. 导入数据:
mysqlimport -u root -p123456 < mysql.dbname。
不用解释了吧。
3. 将文本数据导入数据库:
文本数据的字段数据之间用tab键隔开。
use test;
load data local infile "文件名" into table 表名;
1:使用SHOW语句找出在服务器上当前存在什么数据库:
mysql> SHOW DATABASES;
2:2、创建一个数据库MYSQLDATA
mysql> CREATE DATABASE MYSQLDATA;
3:选择你所创建的数据库
mysql> USE MYSQLDATA; (按回车键出现Database changed时说明操作成功!)
4:查看现在的数据库中存在什么表
mysql> SHOW TABLES;
5:创建一个数据库表
mysql> CREATE TABLE MYTABLE (name VARCHAR(20), sexCHAR(1));
6:显示表的结构:
mysql> DESCRIBE MYTABLE;
7:往表中加入记录
mysql> insert into MYTABLE values ("hyq","M");
8:用文本方式将数据装入数据库表中(例如D:/mysql.txt)
mysql> LOAD DATA LOCAL INFILE "D:/mysql.txt" INTOTABLE MYTABLE;
9:导入.sql文件命令(例如D:/mysql.sql)
mysql>use database;
mysql>source d:/mysql.sql;
10:删除表
mysql>drop TABLE MYTABLE;
11:清空表
mysql>delete from MYTABLE;
12:更新表中数据
mysql>update MYTABLE set sex="f" where name='hyq';13:备份数据库mysqldump -u root库名>xxx.data14:
例2:连接到远程主机上的MYSQL
假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令:
mysql-h110.110.110.110 -uroot -pabcd123
(注:u与root可以不用加空格,其它也一样)
3、退出MYSQL命令:exit
一) 连接MYSQL:
格式: mysql -h主机地址 -u用户名-p用户密码
1、例1:连接到本机上的MYSQL
首先在打开DOS窗口,然后进入mysql安装目录下的bin目录下,例如: D:\mysql\bin,再键入命令mysql -uroot-p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是:mysql>
2、例2:连接到远程主机上的MYSQL
假设远程主机的IP为:10.0.0.1,用户名为root,密码为123。则键入以下命令:
mysql -h10.0.0.1 -uroot-p123
(注:u与root可以不用加空格,其它也一样)
3、退出MYSQL命令
exit (回车)
(二) 修改密码:
格式:mysqladmin -u用户名 -p旧密码password 新密码
1、例1:给root加个密码123。首先在DOS下进入目录C:\mysql\bin,然后键入以下命令:
mysqladmin -uroot -password123
注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。
2、例2:再将root的密码改为456
mysqladmin -uroot -pab12password 456
(三) 增加新用户:(注意:和上面不同,下面的因为是MYSQL环境中的命令,所以后面都带一个分号作为命令结束符)
格式:grant select on 数据库.* to用户名@登录主机 identified by "密码"
例1、增加一个用户test1密码为abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MYSQL,然后键入以下命令:
grantselect,insert,update,delete on *.* to test1@"%" Identified by"abc";
但例1增加的用户是十分危险的,你想如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录你的mysql数据库并对你的数据可以为所欲为了,解决办法见例2。
例2、增加一个用户test2密码为abc,让他只可以在localhost上登录,并可以对数据库mydb进行查询、插入、修改、删除的操作(localhost指本地主机,即MYSQL数据库所在的那台主机),这样用户即使用知道test2的密码,他也无法从internet上直接访问数据库,只能通过MYSQL主机上的web页来访问了。
grantselect,insert,update,delete on mydb.* to test2@localhost identifiedby "abc";
如果你不想test2有密码,可以再打一个命令将密码消掉。
grantselect,insert,update,delete on mydb.* to test2@localhost identifiedby "";
(四) 显示命令
1、显示数据库列表:
show databases;
刚开始时才两个数据库:mysql和test。mysql库很重要它里面有MYSQL的系统信息,我们改密码和新增用户,实际上就是用这个库进行操作。
2、显示库中的数据表:
use mysql; //打开库
show tables;
3、显示数据表的结构:
describe 表名;
4、建库:
create database 库名;
5、建表:
use 库名;
create table 表名(字段设定列表);
6、删库和删表:
drop database 库名;
drop table 表名;
7、将表中记录清空:
delete from 表名;
8、显示表中的记录:
select * from 表名;
MySQL导入导出命令
1.导出整个数据库
mysqldump -u 用户名 -p 数据库名 > 导出的文件名
mysqldump -u wcnc -p smgp_apps_wcnc >wcnc.sql
2.导出一个表
mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名
mysqldump -u wcnc -p smgp_apps_wcnc users>wcnc_users.sql
3.导出一个数据库结构
mysqldump -u wcnc -p -d --add-drop-table smgp_apps_wcnc>d:wcnc_db.sql
-d 没有数据 --add-drop-table 在每个create语句之前增加一个drop table
4.导入数据库
常用source 命令
进入mysql数据库控制台,
如mysql -u root -p
mysql>use 数据库
然后使用source命令,后面参数为脚本文件(如这里用到的.sql)
mysql>source d:wcnc_db.sql (注:如果写成sourced:\wcnc_db.sql,就会报语法
使用load data 批量导入数据,这种做法可以瞬间导入数据,用处非常大!
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS 字段操作,设置每个字段的分隔符
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char' ]
]
[LINES 行操作,从某一个字符开始,到某个字符
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number LINES] 行操作,忽略某行
[(col_name_or_user_var,...)] 字段操作,写入的字段与数据对应
[SET col_name = expr,...)]
示例:load data infile '/test/test.file' intotable 'test' fields terminated by "\t" (fieldsOne,fieldsTwo);
意思是, 载入/test/test.file到表test中,使用\t分割字段,写入fieldsOne和fieldsTwo中,默认以换行符作为一个行分割!
cmd连接mysql
连接:mysql -h主机地址 -u用户名 -p用户密码 (注:u与root可以不用加空格,其它也一样)
断开:exit (回车)
创建授权:grant select on 数据库.* to 用户名@登录主机 identified by \"密码\"
修改密码:mysqladmin -u用户名 -p旧密码 password 新密码
删除授权: revoke select,insert,update,delete om *.* fromtest2@localhost;
显示数据库:show databases;
显示数据表:show tables;
显示表结构:describe 表名;
创建库:create database 库名;
删除库:drop database 库名;
使用库:use 库名;
创建表:create table 表名 (字段设定列表);
删除表:drop table 表名;
修改表:alter table t1 rename t2
查询表:select * from 表名;
清空表:delete from 表名;
备份表: mysqlbinmysqldump -h(ip) -uroot -p(password) databasenametablename > tablename.sql
恢复表: mysqlbinmysql -h(ip) -uroot -p(password) databasenametablename < tablename.sql(操作前先把原来表删除)
增加列:ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,ADDINDEX (c);
修改列:ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b cCHAR(20);
删除列:ALTER TABLE t2 DROP COLUMN c;
备份数据库:mysql\bin\mysqldump -h(ip) -uroot -p(password) databasename> database.sql
恢复数据库:mysql\bin\mysql -h(ip) -uroot -p(password) databasename< database.sql
复制数据库:mysql\bin\mysqldump --all-databases >all-databases.sql
修复数据库:mysqlcheck -A -o -uroot -p54safer
文本数据导入: load data local infile \"文件名\" into table 表名;
数据导入导出:mysql\bin\mysqlimport database tables.txt
mysql安装与卸载(联网)
1、mysql安装:
$>sudo apt-get install libmysqlclient-dev
$>sudo apt-get install mysql-client
$>sudo apt-get install mysql-server
2、mysql卸载:
$>sudo apt-get autoremove --purge mysql*
$>sudo apt-get install mysql-server
$>dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg –P
配置hive schema到mysql中
Hive默认数据库Derby同一时刻只能有一个连接。
1、编写hive-site.xml,添加mysql连接信息
编辑[/soft/hive/conf/hive-site.xml]
javax.jdo.option.ConnectionDriverName</name>
com.mysql.jdbc.Driver</value>
</property>
javax.jdo.option.ConnectionURL</name>
jdbc:mysql://localhost:3306/myhive?createDatabaseIfNotExist=true&useSSL=false</value>
</property>
javax.jdo.option.ConnectionUserName</name>
root</value>
javax.jdo.option.ConnectionPassword</name>
root</value>
</property>
2、在mysql中建立myhive数据库
$>mysql>create database myhive; // 建立hive库
$>mysql>grant all privileges on *.* to root@'%' identified by 'root';
$>mysql>flush privileges;
3、mysql驱动程序(jar)放到hive classpath下
/soft/hive/lib/mysql-connector-java-5.0.8.jar
4、重新初始化hive schema元数据库
$>/soft/hive/bin/schematool -initSchema --dbType mysql
执行完成后会发现mysql的myhive库中有了元数据相关的表,如下图所示:
配置hive的仓库位置
编辑[hive-site.xml]文件,内容如下:
hive.metastore.warehouse.dir=/user/hive/warehouse (此处为默认位置)
❓待解决问题的
show databases; 命令
✏️ 建议:在cmd 进行系统性配置时,尽量不要切换窗口
托管表(内部表)
hive默认创建的表都是托管表,hive控制其数据的生命周期。
删除内部表时,元数据和数据均被删除。
$>hive>create table if not exists myhive.employee_inner(eid int, name String, salary String, destination String) COMMENT 'Employee details' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;
$>hive> drop table myhive.employee_inner;
外部表
hive控制元数据
删除外部表时,元数据删除 但数据不被删除
$>hive>create external table if not exists myhive.employee_outer(eid int, name String, salary String, destination String) COMMENT 'Employee details' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;
分区表
1. 创建分区表
$>hive>create table if not exists myhive.test2(eid int, name String, salary String, destination String) partitioned by(country string,state string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;
2. 加载数据到指定分区
$>hive>load data local inpath '/home/hadoop/Desktop/employee.txt' into table myhive.test2 partition(country='china',state='shanxi');
3. 查看hdfs
$>hdfs dfs -cat
/user/hive/warehouse/myhive.db/test2/country=china/state=shanxi/employee.txt
4. 查询数据
$>hive>select * from myhive.test2 where country='china' and state='shanxi';
5. 分区表的查询模式:strict/nostrict
$>hive>set hive.mapred.mode=strict //严格模式,默认是非严格,严格模式要求查询的时候必须带分区
6. 查看分区表有那些分区
1、查看分区
$>hive>show partitions myhive.test2;
2、查看具体分区的细节信息
$>hive>show partitions myhive.test2 partition(state='shanxi');
3、查看分区信息
$>hive>desc test2;
$>hive>desc myhive.test2; (均可)
4、查看表扩展信息
$>hive>desc extended myhive.test2;
7. 手动增加分区
$>hive>alter table myhive.test2 add partition(country='china',state='henan');
不能增加不存在的分区列
8. 修改表
1、表重命名
$>hive>alter table myhive.test2 rename to myhive.test1; //
2、添加多个分区
$>hive>alter table myhive.test1 add partition(country='china',state='hubei') partition(country='china',state='hebei') partition(country='china',state='shandong') ;
3、移动分区位置
$>hive>alter table myhive.test1 partition(country='china',state='hubei') set location '/user/hive/warehouse/myhive.db/test1/country=china/state=hubei1';
4、增加列
$>hive>alter table myhive.test1 add columns(birth string,fire string) ;
9. 复制数据到分区表
1、创建表test2
$>hive>create table if not exists myhive.test2(eid int, name String, salary String, destination String) partitioned by(country string,state string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;
2、创建表test3
$>hive>create table if not exists myhive.test3(eid int, name String, salary String, destination String) partitioned by(country string,state string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE ;
3、整表复制
$>hive>insert into myhive.test2 partition(country='china',state='henan') select * from myhive.test1;
$>insert into myhive.test2 partition(country='china',state='henan') select eid,name,salary,destination from myhive.test1;
4、部分复制
$>hive>insert into myhive.test2 partition(country='china',state='henan') select eid,name,salary,destination from myhive.test2 (where country='china' and state='henan')括号中可不写,不写的话就是无论啥地儿,统统放入test2的henan;
字段个数要相同。查询时,分区通过where子句指定。插入时,分区用partition指定
这里客户端指eclipse和beeline,客户端通过hiveserver2连接到Hive。所以运行前要保证hiveserver2的开启。
Jdbc连接Hive
创建maven项目
bigdata-hive-2.1.0
配置pom文件
org.apache.hive</groupId>
hive-jdbc</artifactId>
2.1.1</version>
</dependency>
org.apache.hive</groupId>
hive-service</artifactId>
2.1.0</version>
</dependency>
修改hive-site.xml配置文件
修改[/soft/hive/conf/hive-site.xml]配置文件,使用os操作系统的认证方式
hive.server2.enable.doAs=false
hive.metastore.sasl.enabled=false
hive.server2.authentication=NONE
重启hiveserver2服务器
$>hive --service hiveserver2 stop
$>hive --service hiveserver2 start &
$>jobs
书写程序
public class TestHiveConn{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection conn = DriverManager.getConnection("jdbc:hive2://namenode:10000/myhive", "hadoop", "hadoop");
PreparedStatement ppst = conn.prepareStatement("select * from t");
ResultSet rs = ppst.executeQuery();
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + "," + name + "," + age);
}
rs.close();
ppst.close();
conn.close();
}
}
建表,并插入数据
$>hive>create table t(id int,name string,age int);
$>hive>insert into t(id,name,age) values(1,'gxf',23);
运行上面的Java程序进行查询
测试增删改查
package com.ag.hive;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Before;
import org.junit.Test;
/**
* TestCRUD.
*/
public class TestCRUD {
private Connection conn;
/**
* 连接hive数据库.
*/
@Before
public void iniConn() throws Exception {
Class.forName("org.apache.hive.jdbc.HiveDriver");
conn = DriverManager.getConnection("jdbc:hive2://namenode:10000/hive1", "hadoop", "hadoop");
}
/**
* 创建表.
*/
@Test
public void createtable() throws SQLException {
PreparedStatement ppst = conn.prepareStatement("create table users(id int,name string,age int)");
ppst.execute();
ppst.close();
conn.close();
System.out.println("over!");
}
/**
* 批量插入数据.
*/
@Test
public void batchInsert() throws SQLException {
PreparedStatement ppst = conn.prepareStatement("insert into hive1.users(id,name,age) values(?,?,?)");
ppst.setInt(1, 1);
ppst.setString(2, "luke1");
ppst.setInt(3, 30);
ppst.executeUpdate();
ppst.setInt(1, 2);
ppst.setString(2, "luke2");
ppst.setInt(3, 31);
ppst.executeUpdate();
ppst.close();
conn.close();
}
/**
* 删除数据会报错,更新数据也不允许
* 不支持
* @throws SQLException
*/
@Test
public void delete() throws SQLException {
PreparedStatement ppst = conn.prepareStatement("delete from hive1.users");
ppst.executeUpdate();
ppst.close();
conn.close();
}
/**
* 查询记录个数
* @throws SQLException
*/
@Test
public void count() throws SQLException {
PreparedStatement ppst = conn.prepareStatement("select count(*) from hive1.users");
ResultSet rs = ppst.executeQuery();
rs.next();
System.out.println(rs.getInt(1));
ppst.close();
conn.close();
}
/**
* 删除表
* @throws SQLException
*/
@Test
public void droptable() throws SQLException {
PreparedStatement ppst = conn.prepareStatement("drop table hive1.users");
ppst.execute();
ppst.close();
conn.close();
}
Beeline客户端连接Hive
使用Beeline客户端可以实现远程的jdbc连接
1、连接,使用如下命令之一进行连接beeline连接
$>hive --service beeline -u jdbc:hive2://namenode:10000/myhive
$>beeline -u jdbc:hive2://namenode:10000/myhive(这种方式也可以)
2、在beeline中执行命令
$>0: jdbc:hive2://namenode:10000/myhive>!sh clear //执行脚本
$>0: jdbc:hive2://namenode:10000/myhive>show databases; //查看库
$>0: jdbc:hive2://namenode:10000/myhive>!help //查看帮助
3、连接到新的db
$>0: jdbc:hive2://namenode:10000/myhive>!connect jdbc:hive2://namenode:10000/myhive
1、在linux中创建用户
$>groupadd gxf
$>useradd -m -g gxf gxf
$>passwd gxf
2、修改hive-site.xml
hive.users.in.admin.role</name>
hadoop</value>
</property>
3、创建用户,并赋予admin角色
$hive>set role admin; //需要将hadoop用户的“当前角色”切换至admin才可以执行此操作
$hive>grant admin to user gxf with admin option;
4、创建数据库,并修改数据库属主给admin角色
$hive>create database myhive1;
$hive>desc database myhive1;
$hive>alter database myhive1 set owner role admin;
5、插入数据
$>hive>use myhive1;
$>hive>create table t(id int,name string,age int);
$>hive>insert into t(id,name,age) values(1,'gxf',23);
6、在eclipse中写程序进行测试。
$>hive>dfs -lsr /; (HDFS)
$>hive>!clear;
$>hive -e "select * from myhive.test1" //-e execute (非Hive中,可直接用)
$>hive -f /x/x/x/a.hql // 执行一个文件,通常用于批处理
[gxf.hql]
select * from myhive.test1
$>hive -f gxf.hql
$>hive>tab tab //显示所有的命令
$>hive>-- this is a comment
$>hive>set hive.cli.print.header=true; //显示字段名称(头)
$>hive>create database if not exists myhive2;
$>hive>create database hive3 with dbproperties('author'='xupc','createtime'='today');
$>hive>alter database hive3 set dbproperties('author'='you');
$>hive>drop database if exists hive3; //存在即删除
$>hive>drop database if exists hive3 cascade; //级联删除
$>hive>create database hive2 location '/user/hadoop/';
$>hive>desc[ribe] database hive2 //显示db,描述信息,不包含扩展信息
$>hive>desc database extended hive3 //包含扩展信息
$>hive>use hive3 //使用库
$>hive>create table hive1.test1(id int,name string,age int) tblproperties('author'='you');
$>hive>create table hive1.test2(id int,name string,age int) location '/user/hadoop/';
$>hive>desc extended hive1.test1 //显示扩展信息
$>hive>desc formatted myhive.test1; //使用格式化的形式显示信息
$>hive>create table hive2.test1 like hive1.test2 //复制表
$>hive>show tables in myhive; //显示指定数据库的表集合,默认是当前库
$>hive>create external table hive1.test3 like hive1.test1; // 只负责表结构,没有数据
[创建表]
create table if not exists employee(eid int,name string,salary string,destination string)
comment 'employee details' //注释
row format delimited fields terminated by'\t' //字段结束符
lines terminated by '\n' // 行结束符
stored as textfile; //存储成何种文件
[加载数据==insert]
load data local inpath '/home/hadoop/employee.txt' overwrite into table employee;
基本类型
集合类型
STRUCT struct(‘Grolia’,‘Claire’);
MAP map(‘fi’,‘d’,‘ddd’)
ARRAY array(‘Jone’,‘doe’)
例子
Struct使用
$>hive>create table student_test(id INT, info struct
//‘FIELDS TERMINATED BY’ :字段与字段之间的分隔符
//’‘COLLECTION ITEMS TERMINATED BY’ :一个字段各个item的分隔符
// 导入数据
$>hive>LOAD DATA LOCAL INPATH ‘/home/hadoop/gxf/student_test.txt’ INTO TABLE student_test;
// 查询
$>hive>select * from student_test;
$>hive> select info.age from student_test;
Array使用
$>hive>create table class_test(name string, student_id_list array) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’ COLLECTION ITEMS TERMINATED BY ‘:’;
// 导入数据
$>hive>LOAD DATA LOCAL INPATH ‘/home/hadoop/gxf/class_test.txt’ INTO TABLE class_test;
// 查询
$>hive>select student_id_list[3] from class_test;
Map使用
$>hive>create table employee_test(id string, perf map
// 导入数据
$>hive>LOAD DATA LOCAL INPATH ‘/home/hadoop/gxf/employee_test.txt’ INTO TABLE employee_test;
// 查询
$>hive>select * from employee_test;
基本查询
1. 导出数据到目录
$>hive>create table test3 as select id,name from test2 where province='hebei' and city='baoding';
$>hive>--导出hive数据到本地目录(下载)
$>hive>insert overwrite local directory '/home/hadoop/hive' select * from hive1.test1 where province='hebei';
$>hive>--导出hive数据到hdfs目录
$>hive>insert overwrite directory '/user/hadoop/data' select * from hive1.test1 where province='hebei';
$>hive>--查询数据向多个目录同时输送
$>hive>from hive1.test2 t insert overwrite directory '/home/hadoop/hive/hebei' select * where t.province='hebei' insert overwrite directory '/home/hadoop/hive/henan' select * where t.province='henan';
2. 查询语句
2.1. 查询
$>hive>select col1,col2 from table t;
2.2. 使用函数查询
$>hive>select upper(name) from test2; // name大写
$>hive>select lower(name) from test2; // name小写
$>hive>select age + 10 from test2;
2.3. 数学函数
$>hive>select round(12.34); //12 四舍五入
$>hive>select floor(12.34); //12 地板
$>hive>select ceil(12.34); //13 天花板
$>hive>select rand(10); //随机数
2.4. 聚合函数
$>hive>select count(*) from test2;
$>hive>select sum(age) from test2;
$>hive>select avg(age) from test2;
$>hive>select max(age) from test2;
$>hive>select min(age) from test2;
2.5. 去重distinct
$>hive>select count(distinct name) from test2;
2.6. ascii函数
字符串首个字母的ascii值
$>hive>select ascii("abc");
$>hive>select ascii('abc');
2.7. base64字符串编码
$>hive>select base64(binary('http://localhost:8080/helloworld'));
2.8. 二进制数据
$>hive>select binary('http://localhost:8080/helloworld');
2.9. 类型转换
$>hive>select cast('120' as bigint) + 200; //320
$>hive>select '120' + 200; //320.0
2.10. 字符串连接
$>hive>select concat('ab','cd'); //abcd
2.11. 分业查询limit
$>hive>select * from test2 limit 1,2; //从第二条开始,查出来两条
2.12. 嵌套查询
$>hive>from test2 e select e.id,e.name,e.age where e.city='baoding';
$>hive>select e.id,e.name,e.age from test2 e where e.city='baoding';
2.13. case when then
$>hive>select name,age, case when age<20 then 'low' when age>50 then 'old' else 'big' end as agestatus from hive1.test2;
2.14. 不能在where子句中使用列的别名
$>hive>--select id, name n ,age from test2 where n like 't%'; //wrong where中不能使用字段别名
2.15. 范围运算
$>hive>select * from test2 where age between 12 and 24;
$>hive>select * from test2 where age <=24 and age >12;
2.16. 浮点数比较的规避方案
$>hive>select cast(0.2 as float);
$>hive>select 0.2 == cast(0.2 as float);
2.17. 分组查询
$>hive>select count(*),province from test2 group by province;
$>hive>select count(*) as c,province from test2 group by province having c>3;
3. 避免mr操作
不使用mr作业的模式就是本地作业,下面方法可以尽量避免mr作业。
1、全表扫描,没有where子句
$>hive>select * from test;
2、where子句作用只有分区字段,也不需要mr(limit也不需要)
$>hive>select * from test2 where province='hebei';
3、设置
$>hive>set hive.exec.mode.local.auto=true;
该属性hive会尽量使用local模式查询
连接查询
1. 建表
$>hive>create table customers(id int,name string,age int);
$>hive>insert into customers(id,name,age) values(1,'gxf',23);
$>hive>create table orders(id int,cid int,orderno int,price float);
$>hive>insert into orders(id,cid,orderno,price) values(1,1,1,1.2);
$>hive>insert into orders(id,cid,orderno,price) values(1,1,2,3.2);
2. 连接查询
2.1. left semi join
左半连接left semi-join,select和where子句不能引用到右边表字段。左表的记录在右表中一旦找到对应的记录,右侧表立即停止,效率比内连接效率高
hive不支持右半连接操作
$>hive>select c.id,c.name from customers c left semi join orders o on c.id = o.cid;
2.2. 笛卡尔链接m*n
$>hive>select c.id,c.name from customers c join orders o on c.id = o.cid;
2.3. map端连接
map端连接,通过mapper的手段,将一张小表完全载入内存中。
Hive中的Map Join即map side join工作原理是在Map端把小表加载到内存中,然后读取大表,和内存中的小表完成连接操作。MapJoin使用了分布式缓存技术。
Map Join的优点:
1.不消耗集群的reduce资源。
2.减少了reduce操作,加快了程序执行。
3.降低网络负载。
Map Join的缺点:
1.占用内存(所以加载到内存中的表不能过大,因为每个计算节点都会加载一次)。
2.生成较多的小文件。
$>hive>select /*+mapjoin(c)*/ c.id,c.name,o.orderno from customers c join orders o;
$>hive>select /*+mapjoin(o)*/ c.id,c.name,o.orderno from customers c join orders o;
$>hive>set hive.mapjoin.smalltable.filesize=25000000; --设置小表阀值
2.4. union all 联合操作
union all 联合操作,字段的类型和个数需要匹配
$>hive>select id,name from customers union all select id,orderno from orders;
查询拓展
排序
Hive基于HADOOP来执行分布式程序的,和普通单机程序不同的一个特点就是最终的数据会产生多个子文件,每个reducer节点都会处理partition给自己的那份数据产生结果文件,这导致了在HADOOP环境下很难对数据进行全局排序,如果在HADOOP上进行order by全排序,会导致所有的数据集中在一台reducer节点上,然后进行排序,这样很可能会超过单个节点的磁盘和内存存储能力导致任务失败。一种替代的方案则是放弃全局有序,而是分组有序。
1. 全排序
order by 全排序,对所有数据通过一个reduce进行排序
$>hive>select * from orders order by cid asc,price desc; --全局排序
asc---升序
desc---降序
2. 局部排序
sort by 局部排序,每个reduce都会进行排序
$>hive>select * from orders sort by cid asc,price desc; --局部排序
3. distribute by
distribute by 等价于自定义分区函数,要写在sort by 之前
$>hive>select * from orders distribute by cid sort by cid asc,price desc; --先按照cid分区,再局部排序
视图
1. 创建视图
view(虚表),降低查询的复杂度
$>hive>create view view1 as select c.id cid, c.name, c.age, o.id oid, o.orderno, o.price from customers c left outer join orders o on c.id = o.cid;
2. 通过视图直接查询
$>hive>select * from view1 where price>2;
3. 通过视图创建表
$>hive>create table table1 like view1;
$>hive>create table table2 as select * from test2;(另一种通过数据的方法)
4. 删除视图
$>hive>drop view if exists view1;
索引
1. 创建索引
$>hive>-- 索引,hive没有key(primary key, auto_increment)
$>hive>-- 创建索引,deferred rebuild该选项时,索引为空白状态,需要rebuild才能够初始化
$>hive>create index idx_customers_id on table customers(id) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild IN TABLE customers_index;
$>hive>create index idx_orders_orderno on table orders(id) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild in table orders_index;
$>hive>alter index idx_customers_id on customers rebuild; --重建索引,产生索引表,是hdfs的一个文件
hdfs://namenode/user/hive/warehouse/hive1.db/customers/000000_0 --索引文件(表)
$>hive>select * from customers_index; --显示索引表信息
$>hive>show formatted index on customers;
2. 删除索引
$>hive>drop index if exists idx_customers_id on customers;
桶表
在hive中,数据库、表、分区都是对应到hdfs上的路径,当往表中上传数据的时候,数据会传到对应的路径下,形成新的文件,文件名的格式类似为00000_0…每次插入文件都会形成新的文件,命名也是有规律的,桶表就是对应不同的文件的。
hive中有桶的概念,对于每一个表或者分区来说,可以进一步组织成桶,其实就是更细粒度的数据范围。
$>hive>-- 桶表(bucket),是文件。通过hash定位
$>hive>-- 创建桶表
$>hive>--create table ... clustered by (field_name) into n buckets;
$>hive>create table orderitems (id int, itemname string, oid int) clustered by (oid) into 3 buckets row format delimited fields terminated by '\t' lines terminated by '\n' stored as textfile;
$>hive>insert into orderitems(id,itemname,oid) values(1,'water',1);
桶的数量意味着产生文件的数量,那么两个桶就应该使用2个reduce任务来完成,但是默认情况下hive只启动一个reducer,所以要修改reducer的数量,可以通过设置强制分桶机制来保证reducer数量和桶的数量一致。
$>hive>set hive.enforce.bucketing = true;
1. explain
解释执行计划
$>hive>explain select count(*) from test2;
2. limit
启用limit优化,避免全表扫描,使用抽样机制。
$>hive>select * from test2 limit 1,2;
3. join
使用map端连接/*+ mapjoin (table)*/
$>hive>select /*+mapjoin(c)*/ c.id,c.name,o.orderno from customers c join orders o;
4. 设置本地模式,在单台机器上处理所有任务
适用于小数据情况
$>hive>set hive.exec.mode.local.auto=true; // 默认false
$>hive>set mapreduce.framework.name=local;
5. 并行执行job
如果job之间没有依赖关系,可以并发执行,缩短执行时间
$>hive>set hive.exec.parallel=true; // 默认false
6. 严格模式
$>hive>set hive.mapred.mode=strict; // 默认false,该设置会禁用以下操作:
1、不指定limit的order by
2、对分区表不指定分区进行查询
3、和数据量无关,只是一个查询模式
7. 调整reducer的个数
$>hive>set hive.exec.reducers.bytes.per.reducer=256000000; // 每个reducer大小,默认256M
$>hive>set hive.exec.reducers.max=1009; //最大多少个reducers被使用
8. jvm重用
使得同一个jvm在一个job(map*,reduce*)中执行多次,避免启动jvm的开销。
$hive>set mapreduce.job.ubertask.enable=true; //是否启用uber,jvm重用
$hive>set mapreduce.job.ubertask.maxmaps=10; // mapper最大数
$hive>set mapreduce.job.ubertask.maxreduces=3; // reduce最大数
9. 索引
使用index
10. 动态分区调整、bucket表
$hive>set hive.exec.dynamic.partition.mode=strict; // 动态分区严格模式
$hive>set hive.exec.max.dynamic.partitions=300000; // 最大分区数
$hive>set hive.exec.max.dynamic.partitions.pernode=10000; // 每个节点的最大分区数
11. 推测执行,让map|reduce多个实例并发执行
原来hadoop在分配完map reduce task后,会预测性的判断某个map 或reduce task所在的节点资源有限,执行会比较慢。
因此他在资源更多的节点上会启动一个完全一样的map或 reduce task,同时执行,哪个先完成,就将未完成的那个task kill掉,这样可以提高整体job效率。
$hive>set mapreduce.map.speculative=true; // map推测
$hive>set mapreduce.reduce.speculative=true; // reduce推测
12. 虚拟列
$hive>set hive.exec.rowoffset=true; // 是否启用虚拟列
$hive>select INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE, name from test2; // INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE是虚拟列
13. 压缩
13.1. 启用中间结果压缩(map输出,reduce输入)
$hive>set hive.exec.compress.intermediate=true; // 启用压缩
修改map输出结果的压缩类型,默认值是DefaultCodec
[mapred-site.xml]
mapred.map.output.compression.codec</name>
org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
13.2. 设置最终的job输出压缩
1、设置hive的查询结果是否压缩
$hive> set hive.exec.compress.output=true; // 默认false,不压缩
2、设置压缩类型,具体配置要依靠hadoop配置
[mapred-site.xml]
mapred.output.compression.codec</name>
org.apache.hadoop.io.compress.GzipCodec</value>
</property>
13.3. 使用sequencefile作为存储格式(默认是record压缩)
$hive>create table t_seq(id int,name string,age int) stored as sequencefile; // 使用序列文件存储
$hive>insert into t_seq select * from myhive.t; // 复制test1数据到t_seq
13.4. 例子:控制sequencefile中map端输出时文件的压缩类型,使用block压缩
1、中间结果压缩
$hive>set hive.exec.compress.intermediate=true; // 中间结果是否压缩,作为是否压缩的控制阀门
$hive>set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec; // map输出codec
2、job结果压缩
$hive>set hive.exec.compress.output=true; // job的输出是否压缩,作为是否压缩的控制阀门
$hive>set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec; //job输出的codec
$hive>set mapred.output.compression.type=BLOCK; //job的输出block压缩
函数操作
$hive>show functions; // 显示所有函数
$hive>desc function case; // 查看函数帮助(describe)
$hive>desc function extended case; // 查看函数扩展帮助(细粒度)
自定义函数
UDF用户自定义函数。
创建类继承UDF
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
@Description(name = "to_date", value = "to date udf!", extended = "For example : select to_date('2020/09/17 12:12:12');")
public class UDFTest extends UDF {
public Date evaluate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyy/MM/dd HH:mm:ss");
try {
return sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return new Date();
}
}
-------------------------
将函数导出jar包
mvn package -DskipTests(或者通过eclipse也可以直接导出)
通过hive命令将jar添加到hive类路径
$hive>add jar /home/hadoop/tools/bigdata-hive-2.1.0-0.0.1-SNAPSHOT.jar;
注册函数
$hive>create temporary function to_date as 'com.gxf.hive.func.UDFTest';
调用函数
$hive>desc function to_date;
$hive>desc function extended to_date;
$hive>select to_date('2020/09/17 12:12:12');
自定义表生成函数UDTF。User Define table function,表生成函数n个输入,多行或者多列作为输出
例如:
$hive>select array(1,2,3);
$hive>select explode(array(1,2,3));
创建类UDTF,继承GenericUDTF
import java.util.ArrayList;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableConstantIntObjectInspector;
import org.apache.hadoop.io.IntWritable;
@Description(name = "forx", value = "this is my first UDTF!", extended = "For example : select forx(1,10,1);")
public class UDTFTest extends GenericUDTF {
IntWritable start;
IntWritable end;
IntWritable inc; // increment
private Object[] forwardObj;
public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {
start = ((WritableConstantIntObjectInspector) args[0]).getWritableConstantValue();
end = ((WritableConstantIntObjectInspector) args[1]).getWritableConstantValue();
if (args.length == 3) {
inc = ((WritableConstantIntObjectInspector) args[2]).getWritableConstantValue();
} else {
inc = new IntWritable(1);
}
this.forwardObj = new Object[1];
ArrayList<String> fieldNames = new ArrayList<String>();
ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
fieldNames.add("col0");
fieldOIs.add(PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(PrimitiveCategory.INT));
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
}
@Override
public void close() throws HiveException {
}
@Override
public void process(Object[] arg0) throws HiveException {
for (int i = start.get(); i < end.get(); i = i + inc.get()) {
this.forwardObj[0] = new Integer(i);
forward(forwardObj);
}
}
}
-------------------------
将函数导出jar包
mvn package -DskipTests
通过hive命令将jar添加到hive类路径
$hive>add jar /home/hadoop/tools/bigdata-hive-2.1.0-0.0.1-SNAPSHOT.jar;
注册函数
$hive>create temporary function forx as 'com.gxf.hive.func.UDTFTest';
调用函数
$hive>select forx(1,10);
特别鸣谢-人员
ZhangWen
WangSheng
LazyHou
LiMingyu
ZhaoXu
HuChuan
AG
特别鸣谢-文章
Hadoop各进程启动命令
https://blog.csdn.net/qq_40513633/article/details/80725474
FAILED: SemanticException org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.RuntimeExcepti
https://blog.csdn.net/qq_35078688/article/details/86137440
在hive中执行sql语句:SemanticException org.apache.hadoop.hive.ql.metadata.HiveException:[TEAM_AG采用]
https://blog.csdn.net/estelle_belle/article/details/89469581
cmd连接mysql连接:mysql-h主机地址-u用户名-p用户密码(注:u与root可以不用加)
https://www.cnblogs.com/kpengfang/p/5201285.html
Your password does not satisfy the current policy requirements
https://blog.csdn.net/hello_world_qwp/article/details/79551789
linux find 命令查找文件和文件夹
https://www.cnblogs.com/jiftle/p/9707518.html
Schema initialization FAILED! Metastore state would be inconsistent !
https://blog.csdn.net/zzw_17600691357/article/details/89667881
WARN: Establishing SSL connection without server’s identity verification is not recommended【TEAM-AG采用】
https://blog.csdn.net/lukabruce/article/details/102837226
Ubuntu 修改终端显示的主机名和用户名
https://www.linuxidc.com/Linux/2020-01/162067.htm
linux查看当前登录用户名
https://blog.csdn.net/qq_37960324/article/details/82251328用户名 >whoami
主机名 >hostnameLinux系统中的权限详解
https://www.cnblogs.com/songgj/p/8890710.html
TEAM-AG 本文相关工作人员
WuKai
LiXing
WenWen
LiJia
WangYujia
AG