Hivephp
Day01java
Hive是由Facebook開源,構建於hadoop之上的數據倉庫工具,將結構化的數據映射成一張表格,提供了類SQL查詢語句,底層能夠轉化爲Mapreduce去執行。node
1、Hive體系python
Hive是構建於hadoop之上的數據倉庫工具,將結構化的數據映射成一張表格,提供了類SQL的查詢語句,底層能夠轉化成MapReduce去執行。mysql
1、用戶接口linux
CLI command Line 元數據web
java JDBC/ODBC 元數據 正則表達式
Web UI 瀏覽器 元數據算法
2、Metastore sql
Hive將元數據存儲在數據庫中,好比mysql ,derby.Hive中的元數據包括表的名稱,表的列和分區及其屬性,表的數據所在的目錄
3.驅動器:Driver
包含:解析器、編譯器、優化器、執行器;
4.Hive數據存儲在HDFS,大部分的查詢、計算由mapreduce完成
5.Hive數據倉庫於數據庫的異同
(1).因爲Hive採用了SQL的查詢語言HQL,所以很容易將Hive理解爲數據庫。其實從結構上來看,Hive和數據庫除了擁有相似的查詢語言,再無相似之處。
(2)數據存儲位置。 hdfs raw local fs
(3)數據格式。 分隔符
(4)數據更新。hive讀多寫少。Hive中不支持對數據的改寫和添加,全部的數據都是在加載的時候中肯定好的。
INSERT INTO … VALUES添加數據,使用UPDATE … SET修改數據 不支持的
HDFS 一次寫入屢次讀取
(5) 執行。hive經過MapReduce來實現的 而數據庫一般有本身的執行引擎。
(6)執行延遲。因爲沒有索引,須要掃描整個表,所以延遲較高。另一個致使Hive執行延遲高的因素是MapReduce框架
(7)可擴展性
(8)數據規模。
2、Hive的安裝模式
1、嵌入模式
2、本地模式
3、遠程模式
3、安裝Hive
(一)Linux安裝MySQL是在root用戶下安裝的mysql
1)首先卸載自帶的MySQL數據庫
# rpm -qa | grep mysql
# rpm -e mysql-libs-5.1.71-1.el6.x86_64 --nodeps
2)經過yum安裝mysql
# yum install -y mysql-server mysql mysql-devel
3)啓動mysql服務(mysqld)
# service mysqld start
4)設置爲開機啓動
# chkconfig --list | grep mysqld //查看是否爲開機
# chkconfig mysqld on //設置開機啓動
5)登錄mysql數據庫
# mysql -u root -p
6)設置或密碼
方式一:
# /usr/bin/mysqladmin -u root password 'root'
方式二:
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('root123');
7)受權root的權限
mysql> grant all privileges on *.* to 'root'@'%' identified by 'root';
mysql> grant all privileges on *.* to 'root'@'chao.com' identified by 'root';
all privileges:添加全部權限
第一個*:全部數據庫
第二個*:全部表
第一個'root':表明root用戶
%:表明其餘的外部主機
'root123' :表明root用戶密碼
## 刷新權限
flush privileges;
(二)安裝Hive
1解壓hive的tar包
$ tar -zxf hive-0.13.1-bin.tar.gz -C ../modules/
2.建立/tmp和hive數據倉庫在HDFS之上的目錄
須要開啓namenode datanode
$ bin/hdfs dfs -mkdir -p /user/hive/warehouse
$ bin/hdfs dfs -mkdir /tmp //默認已經建立了
修改目錄的權限(增長組用戶的寫權限)
bin/hdfs dfs -chmod g+w /user/hive/warehouse
bin/hdfs dfs -chmod g+w /tmp
3.${HIVE_HOME}/conf/ 重命名生成配置文件
$ cp hive-env.sh.template hive-env.sh
$ cp hive-default.xml.template hive-site.xml
$ cp hive-log4j.properties.template hive-log4j.properties
4.${HIVE_HOME}/conf/ 修改hive-env.sh
JAVA_HOME=/opt/modules/jdk1.7.0_67
HADOOP_HOME=/opt/modules/hadoop-2.5.0
export HIVE_CONF_DIR=/opt/modules/apache-hive/conf
5)${HIVE_HOME}/conf/ 修改hive-site.xml
--JDBC鏈接的四要素:ConnectionURL DriverName UserName Password
<--!132--> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://[hostname]:3306/metastore?createDatabaseIfNotExist=true</value> <description>JDBC connect string for a JDBC metastore</description> </property> <--!138--> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> <description>Driver class name for a JDBC metastore</description> </property> <--!162--> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>root</value> <description>username to use against metastore database</description> </property> <--!168--> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>root123</value> <description>password to use against metastore database</description> </property>
|
6)拷貝jdbc驅動包到${HIVE_HOME}/lib
$ cp mysql-connector-java-5.1.34-bin.jar ../ruan/hive/lib/
4、Hive基本操做
一)啓動Hive的條件
1.檢查hadoop的相關進程
$ jps
26514 SecondaryNameNode
27934 ResourceManager
28033 NodeManager
26232 NameNode
28590 Jps
26329 DataNode
2.啓動進入Hive CLI
${HIVE_HOME}/bin存放的hive的啓動命令
$ bin/hive
啓動以後檢查mysql數據庫中metastore數據庫是否自動建立成功
3.Hive表建立
//建立數據庫
create database db01;
//建立表
create table student(
id int,
name string,
age int
)
row format delimited fields terminated by '\t'; //指定表格字段的分隔符
//加載數據
load data local inpath ‘/user/hive/student.txt’ into table student;
//查詢數據
select * from student;
3.修改${HIVE_HOME}/conf/ 修改hive-site.xml
顯示當前所在的數據庫名和查詢結果的字段名
<--!55--> <property> <name>hive.cli.print.header</name> <value>true</value> <description>Whether to print the names of the columns in query output.</description> </property> <--!61--> <property> <name>hive.cli.print.current.db</name> <value>true</value> <description>Whether to include the current database in the Hive prompt.</description> </property> |
建立/刪除/清空表基本語法
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later)
[(col_name data_type [COMMENT col_comment], ... [constraint_specification])]
[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]
[SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)]
ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
[STORED AS DIRECTORIES]
[
[ROW FORMAT row_format]
[STORED AS file_format]
| STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later)
]
http://chao.com:50075/browseDirectory.jsp
表類型1、管理表或內部表Table Type: MANAGED_TABLE
create table if not exists dept2(
deptno int,
deptname string,
address string
)
row format delimited fields terminated by '\t';
//加載HDFS文件到Hive表中
load data inpath '/input/dept.txt' into table dept;
//用來指定原文件的列分隔符
row format delimited fields terminated by '\t';
load 若是操做的HDFS上的文件,表明着會移動或者剪切文件
desc formatted dept; //描述表結構信息
Location: hdfs://bigdata.ibeifeng.com:8020/user/hive/warehouse/db01.db/dept
Table Type: MANAGED_TABLE
表類型2、外部表
create external table emp(
empno int,
empname string,
empjob string,
mgno int,
birthday string,
salary float,
bonus float,
depno int
)
row format delimited fields terminated by '\t'
location '/input/demo';
//描述表結構
desc formatted emp;
Location: hdfs://bigdata.ibeifeng.com:8020/input/demo
Table Type: EXTERNAL_TABLE
刪除內部表
drop table dept;
刪除外部表
drop table emp;
清空表數據
truncate table student;
內部表和外部表的區別:
建立表
外部表建立表的時候,不會移動數到數據倉庫目錄中(/user/hive/warehouse),只會記錄表數據存放的路徑
內部表會把數據複製或剪切到表的目錄下
刪除表
外部表在刪除表的時候只會刪除表的元數據信息不會刪除表數據
內部表刪除時會將元數據信息和表數據同時刪除
表類型3、分區表
create table emp_part(
empno int,
empname string,
empjob string,
mgrno int,
birthday string,
salary float,
bonus float,
deptno int
)
partitioned by (province string)
row format delimited fields terminated by '\t';
//向分區表加載數據
load data local inpath '/home/gu/mystudent/emp.txt ' into table emp_part partition (province='CHICAGO');
//描述表信息
desc formatted emp_part;
//查詢全表數據
select * from emp_part;
//查詢分區字段表數據
select * from part where province='CHICAGO';
//查看分區信息
show partitions emp_part;
//增長分區
aler table emp_part add [if not exist] partition(provine='zhejiang',city='hangzhou')
//刪除分區
aler table emp_part drop [if exist] partition(provine='zhejiang',city='hangzhou')
分區表建立表的時候須要指定分區字段,分區字段與普通字段的區別:分區字段會在HDFS表目錄下生成一個分區字段名稱的目錄,而普通字段則不會,查詢的時候能夠當成普通字段來使用,通常不直接和業務直接相關。
(二)與其餘文件系統的交互
1.與Linux系統交互
!ls /opt/sofware/;
2.與hdfs文件系統的交互
dfs -ls /input
dfs -mkdir /hive
3. show databases --顯示數據庫; //能夠直接使用--對語句進行註釋
Day02
二級分區表/管理表
create table emp_part1(
empno int,
empname string,
empjob string,
mgrno int,
birthday string,
salary float,
bonus float,
deptno int
)
partitioned by (day string,hour string)
row format delimited fields terminated by '\t';
load data local inpath '/home/user01/emp.txt' into table emp_part1 partition (day='20170308',hour='9');
load data local inpath '/home/user01/emp.txt' into table emp_part1 partition (day='20170308',hour='10');
load data local inpath '/home/user01/emp.txt' into table emp_part1 partition (day='20170308',hour='14');
load data local inpath '/home/user01/emp.txt' into table emp_part1 partition (day='20170309',hour='10');
select * from emp_part1;
select * from emp_part1 where day='20170308'
select * from emp_part1 where day='20170308' and hour='14';
***分區能夠理解爲分類,經過分類把不一樣類型,時間,地域的數據放到不一樣的目錄下。
分類的標準就是分區字段,能夠一個,也能夠多個。
分區表的意義在於優化查詢。查詢時儘可能利用分區字段。若是不使用分區字段,就會全表掃描。
##增長分區
alter table emp_part1 add partition (day='20170306',hour='0');
刪除分區
alter table emp_part1 drop partition (day='20170306',hour='0');
【擴展】
[動態分區表]
嚴格模式:static partitioned by (county string,states string)
非嚴格模式:partitioned by (county string,states string)
【擴展】
表類型四:桶表
將內部表,外部表和分區表進一步組織成桶表
能夠將表的列經過Hash算法進一步分解成不一樣的文件存儲
create table test_bucket_table(
id int,
name string
)
clustered by (id) into 5 bucket;
表類型五:臨時表 TEMPORARY hive-0.14之後支持
========================================
1、Hive建立表與加載表,導出的數據的方式
(一)建立表的方式
##方式一 create + load
create [external] table table_name(
col1_name col1_type,
...
coln_name coln_type
)
row format delimited fields terminated by '\t';
//load加載數據
laod data [local] inpth '本地文件(linux)/HDFS' [overwrite] into table table_name;
##方式二 like + load
##複製表結構
create table tableB like tableA; //首先必需要有tableA
//load加載數據
laod data [local] inpth '本地文件(linux)/HDFS' [overwrite] into table table_name;
*** ##方式三 as 建立表的同時加載數據
create table tableB row format delimited filelds termianted by ',' as select * from tableA; //首先必需要有tableA
create table emp_as row format delimited fields terminated by ',' as select empno,empname,salary from emp_part1;
*** ##方式四 create + insert
1.建立表
create table emp_insert(
id int,
name string,
job string,
salary float
)
row format delimited fields terminated by ',';
2.insert into 加載數據
insert into table emp_insert select empno,empname,empjob,salary from emp_part1 where day='20170308' and hour='14';
(二)加載數據的方式
加載方式一
1.加載本地文件到Hive表 --使用存儲介質(移動硬盤)
laod data local inpth '本地文件(linux)' [overwrite] into table table_name;
2.加載HDFS文件到hive表 --經過Flume等日誌收集框架
laod data inpth 'HDFS文件' [overwrite] into table table_name;
3.加載數據示覆蓋已有的數據
laod data [local] inpth '文件' overwrite into table;
**hdfs dfs -put 本地目錄及文件 表在HDFS所在的目錄
desc formatted table_name; --找到table_name在HDFS上的目錄
4.建立表時經過select查詢語句加載數據
create table tableB row format delimited filelds termianted by ',' as select * from tableA; 5.先建立表,經過insert into table table_namea select * fom tableB
6.建立外部表示經過location指定數據所在目錄
create extrnal table_name(
col1_name col1_type,
...
coln_name coln_type
)
row format delimited fields terminated by '\t';
location 'HDFS上的目錄'
(三)幾種導出數據的方式
1.insert overwrite ... 導出到本地目錄
insert overwrite local directory '/home/user01/export' row format delimited fields terminated by ' ' select * from emp_part1;
2.insert overwrite ... 導出到HDFS之上
insert overwrite directory '/export' select * from emp_part1 where day='20170308';
3.hive -e 'HQL query' >> test
bin/hive -e 'select * from db01.student' >> test.txt
4)sqoop
3、基本查詢
SELECT [DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]
1.查詢表中的某幾個字段
select empno,empname from emp;
2.distinct 去重
select distinct(depno) from emp;
3.count 統計計數
select count(empno) from emp;
select count(*) from emp;
select count(1) from emp;
4.別名
select count(empno) as empnonum from emp a;
5.where
** and
** or
** between ... and ..
** + - * /
** < > = >= <=
** is null is not null
select * from emp where depno=20;
select * from emp where depno=20 and salary > 2000;
select * from emp where depno=20 or empno=7521;
select * from emp where salary between 2000 and 5000;
select * from emp where salary > 3000;
select empname, salary, bonus,(salary+bonus) as tolsal from emp;
select *
6.limit from emp limit 2;
7.聚合函數
** count
count(*) -全部值不全爲null時,加1操做
count(1) -無論有沒有值,只要有這條記錄,值就加1
count(col) -col列裏面的值爲null,值不會加1,這個列的值不爲null,才加1
select count(bonus) from emp;
** avg 平均值
** sum 求和
** max 最大值
** min 最小值
select avg(salary) salary from emp;
select depno,avg(salary) salary from emp group by depno;
select depno,max(salary) salary from emp group by depno;
select depno,min(salary) salary from emp group by depno;
8.group by
* 求每一個部門的薪資總和
select depno,sum(salary) sum_salary from emp group by depno;
* 求每一個部門的薪資最高的員工,薪水
【錯誤】select empname,max(salary) salary from emp group by depno;
FAILED: SemanticException [Error 10025]: Line 1:7 Expression not in GROUP BY key 'empname'
Error: Error while compiling statement: FAILED: SemanticException [Error 10025]: Line 1:7 Expression not in GROUP BY key 'empname' (state=42000,code=10025)
***注意:group by 後面沒有出現的字段,不能直接放到select後面,爲了構成語法,能夠結合聚合函數使用。
FAILED: SemanticException [Error 10025]: Line 1:7 Expression not in GROUP BY key 'empname'
【語法正確-結果錯誤,須用子查詢方式】select max(empname),max(salary) max_sal from emp group by deptno;
select e.empno,e.empname,e.salary,e.depno from emp e where e.salary in (select max(salary) salary from emp group by depno);
elect e.empname from emp e where e.deptno in (select d.deptno from dept d where d.deptname='SALES' or d.deptname='ACCOUNTING');
Hive的子查詢
Hive只支持where和from後面的子查詢
-語法中的括號
-合理的書寫風格
-hive只支持where和from語句中的子查詢
-主查詢和子查詢能夠不是同一張表
-子查詢中的空值問題
9.having 條件過濾
select depno, avg(salary) avg_sal from emp group by depno hvaing avg_sal >3000;
10.union union all
必須保證union all 先後select 查詢字段的個數和字段類型相同
select depno from emp
union all
select depno from dept;
11 join (map join, reduce join, SMB join)
* on 條件 --等值鏈接
查詢員工姓名、部門名稱及員工薪資
select a.empname,b.deptname,a.salary from emp a join dept b on a.depno=b.depno;
//左連
select a.empname,b.deptname,a.salary from emp a left join dept b on a.depno=b.depno;
//右連
select a.empname,b.deptname,a.salary from emp a right join dept b on a.depno=b.depno;
兩張表中沒有共同字段作jion
select * from student join dept on 1=1;
4、數據類型 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
基本數據類型 和 複雜類型
基本數據類型
Numeric Types
TINYINT
SMALLINT
INT/INTEGER
BIGINT
FLOAT
DOUBLE
DOUBLE PRECISION
DECIMAL
Date/Time Types
TIMESTAMP
DATE
INTERVAL
String Types
STRING
VARCHAR
CHAR
Misc Types
BOOLEAN
BINARY (Note: Only available starting with Hive 0.8.0)
複雜數據類型:
- Array:數組類型,由一系列相同數據類型的元素組成
- Map:集合類型,包括key -> Value 鍵值對,能夠經過key來訪問元素[key相同的會被覆蓋]
- Struct:結構類型,能夠包含不一樣數據類型的元素。這些元素能夠經過「點語法」的方式來獲得所須要的元素
【擴展】
create table people_movie(
name string, --學生名稱
movie map<string,string> ) --電影名稱,女一號
row format delimited fields terminated by "\t"
collection items terminated by ","
map keys terminated by ":";
vi movie.txt
A ABC:2016-05,EFG:2016-09
B OPQ:2015-06,XYZ:2016-04
select * from people_movie;
A {"ABC":"2016-05","EFG":"2016-09"}
B {"OPQ":"2015-06","XYZ":"2016-04"}
create table student(
sid int,
sname string,
grade arrary<float>)
id name grade(英語,語文,數學)
{1 Tom [80, 90, 75]}
create table student3(
sid int,
info struct<name:string,age:int,sex:string>);
{1, {'Tom',10,'男'}}
5、Hiveserver2 應用場合:beeline java代碼JDBC
hiveserver:這個可讓Hive以提供Trift服務的服務器形式來運行,能夠容許許多不一樣語言編寫(C python java)的客戶端進行通訊。使用須要啓動HiveServer服務以和客戶端聯繫,咱們能夠經過設置HIVE_PORT環境變量來設置服務器所監聽的端口號,在默認的狀況下,端口爲10000。能夠經過下面方式來啓動HiveServer:
bin/hive --service hiveserver2 &
hiveServer/HiveServer2
1:簡單介紹
二者都容許遠程客戶端使用多種編程語言,經過HiveServer或者HiveServer2,客戶端能夠在不啓動CLI的狀況下對Hive中的數據進行操做,連這個和都容許遠程客戶端使用多種編程語言如java,python等向hive提交請求,取回結果(從hive0.15起就再也不支持hiveserver了),可是在這裏咱們仍是要說一下hiveserver
HiveServer或者HiveServer2都是基於Thrift的,但HiveSever有時被稱爲Thrift server,而HiveServer2卻不會。既然已經存在HiveServer,爲何還須要HiveServer2呢?這是由於HiveServer不能處理多於一個客戶端的併發請求,這是因爲HiveServer使用的Thrift接口所致使的限制,不能經過修改HiveServer的代碼修正。所以在Hive-0.11.0版本中重寫了HiveServer代碼獲得了HiveServer2,進而解決了該問題。HiveServer2支持多客戶端的併發和認證,爲開放API客戶端如JDBC、ODBC提供更好的支持。
2:二者的區別
Hiveserver1 和hiveserver2的JDBC區別:
version Connection URL Driver Class
HiveServer2 jdbc:hive2://: org.apache.hive.jdbc.HiveDriver
HiveServer1 jdbc:hive://: org.apache.hadoop.hive.jdbc.HiveDriver
修改${HIVE_HOME}/conf/hive-site.xml
<--!2157--> <property> <name>hive.server2.long.polling.timeout</name> <value>5000</value> </property>
<--!2170--> <property> <name>hive.server2.thrift.port</name> <value>10000</value> </property>
<--!2177--> <property> <name>hive.server2.thrift.bind.host</name> <value>bigdata.ibeifeng.com</value> </property>
|
2.在//mysql數據庫中建立一個普通用戶
(等同於操做hdfs的用戶名和密碼)
//建立用戶
CREATE USER 'gu'@'chao.com' IDENTIFIED BY 'gu';
//爲新建用戶受權訪問hive在mysql的hive的元數據的數據庫
GRANT ALL ON metastore.* TO 'chao'@'chao.com' IDENTIFIED BY 'chao';
GRANT ALL ON metastore.* TO 'chao'@'%' IDENTIFIED BY 'chao';
//刷新受權
flush privileges;
3.beeline的使用
啓動hiveserver2
bin/hive --service hiveserver2 //前臺命令,會駐留到控制檯
可使用以下命令將前臺轉後臺
bin/hive --service hiveserver2 & //前臺轉後臺,啓動完成,按回車能夠繼續進行其餘操做
使用以下命令確認hiveserver2進程是否啓動成功
netstat -antp | gerp 10000
//其中13154就是hiveserver2的進程
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 192.168.7.7:10000 0.0.0.0:* LISTEN 13154/java
結束進程的命令:$ kill -9 13154
$ bin/beeline
beeline>!connect jdbc:hive2://bigdata.ibeifeng.com:10000
Enter username for jdbc:hive2://bigdata.ibeifeng.com:10000: --輸入mysql的用戶名
Enter password for jdbc:hive2://bigdata.ibeifeng.com:10000:--輸入mysql密碼
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;
import org.apache.log4j.Logger;
/** * Handle data through hive on eclipse * @author urey * @time 2013\12\26 19:14 */ public class HiveJdbcClient {
private static String driverName = "org.apache.hive.jdbc.HiveDriver"; private static String url = "jdbc:hive2://[hostname]:10000/default"; private static String user = ""; private static String password = ""; private static String sql = ""; private static ResultSet res; private static final Logger log = Logger.getLogger(HiveJdbcClient.class);
public static void main(String[] args) { try { Class.forName(driverName); //Connection conn = DriverManager.getConnection(url, user, password); //默認使用端口10000, 使用默認數據庫,用戶名密碼默認 Connection conn = DriverManager.getConnection("jdbc:hive://[hostname]:10000/metastore", "user01", "1233456"); Statement stmt = conn.createStatement();
// 建立的表名 String tableName = "testHiveDriverTable";
/** 第一步:存在就先刪除 **/ sql = "drop table " + tableName; stmt.executeQuery(sql);
/** 第二步:不存在就建立 **/ sql = "create table " + tableName + " (key int, value string) row format delimited fields terminated by '\t'"; stmt.executeQuery(sql);
// 執行「show tables」操做 sql = "show tables '" + tableName + "'"; System.out.println("Running:" + sql); res = stmt.executeQuery(sql); System.out.println("執行「show tables」運行結果:"); if (res.next()) { System.out.println(res.getString(1)); }
// 執行「describe table」操做 sql = "describe " + tableName; System.out.println("Running:" + sql); res = stmt.executeQuery(sql); System.out.println("執行「describe table」運行結果:"); while (res.next()) { System.out.println(res.getString(1) + "\t" + res.getString(2)); }
// 執行「load data into table」操做 String filepath = "/home/hadoop/file/test2_hive.txt"; sql = "load data local inpath '" + filepath + "' into table " + tableName; System.out.println("Running:" + sql); res = stmt.executeQuery(sql);
// 執行「select * query」操做 sql = "select * from " + tableName; System.out.println("Running:" + sql); res = stmt.executeQuery(sql); System.out.println("執行「select * query」運行結果:"); while (res.next()) { System.out.println(res.getInt(1) + "\t" + res.getString(2)); }
// 執行「regular hive query」操做 sql = "select count(1) from " + tableName; System.out.println("Running:" + sql); res = stmt.executeQuery(sql); System.out.println("執行「regular hive query」運行結果:"); while (res.next()) { System.out.println(res.getString(1));
}
conn.close(); conn = null; } catch (ClassNotFoundException e) { e.printStackTrace(); log.error(driverName + " n5ot found!", e); System.exit(1); } catch (SQLException e) { e.printStackTrace(); log.error("Connection error!", e); System.exit(1); }
} } |
Day03
SQOOP SQL-TO-Hadoop
Apache Sqoop(TM) is a tool designed for efficiently transferring bulk data between Apache Hadoop and structured datastores such as relational databases.
1.SQOOP的使用要點
RDBMS:關係數據庫訪問操做四要素
1)jdbcurl //鏈接url
2)username //用戶名
3)password //密碼
4)tablename //操做表名
Ways:以HDFS/hive爲參照,肯定導入導出方向
1)improt mysql --> Hive/HDFS //導入
2)export Hive/HDFS --> mysql //導出
數據存放的載體
1)HDFS ;
path
2)hive
tablename
操做數據的目的
* RDBMS 導入到HDFS/hive上面
**把關係型數據庫的表(歷史數據)導入到HDFS/Hive作數據分析
* hive 表的數據導出到RDBMS
** Hive的分析結果導出到MySQL作業務展現
1、搭建SQOOP
1.${SQOOP_HOME}/conf/
$ cp sqoop-env-template.sh sqoop-env.sh //拷貝模板生成配置環境目錄
=============修改sqoop-env.sh 配置文件
#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/opt/modules/cdh/hadoop-2.5.0-cdh5.3.6
#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/opt/modules/cdh/hadoop-2.5.0-cdh5.3.6
#set the path to where bin/hbase is available
#export HBASE_HOME=
#Set the path to where bin/hive is available
export HIVE_HOME=/opt/modules/cdh/hive-0.13.1-cdh5.3.6
#Set the path for where zookeper config dir is
export ZOOCFGDIR=/opt/modules/cdh/zookeeper-3.4.5-cdh5.3.6/conf
==========================
2.拷貝mysql的jdbc驅動包到${SQOOP_HOME}/lib
$ cp mysql-connector-java-5.1.34-bin.jar /opt/modules/cdh/sqoop-1.4.5-cdh5.3.6/lib/
##測試鏈接--MySQL
bin/sqoop list-databases \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306 \
--username root \
--password root123
Preparing to use a MySQL streaming resultset.
information_schema
cdhmetastore
metastore
mysql
test
3.SQOOP的導入
首先在MySQL中使用下面的命令建立測試用的數據庫和表,同時爲表插入數據
create database testdb;
use testsb;
create table user(
id int not null auto_increment,
account varchar(10) default null,
password varchar(10) default null,
primary key(id)
);
insert into user (account,password) values ("aaa","123");
insert into user values ("aaa","123");
update user set password="213" where id=2;
insert into user values (null,"ccc","321");
insert into user values (null,"ddd","456");
insert into user values (null,"eee","546");
insert into user(account,password) values("fff","654");
insert into user(account,password) values("ggg","789");
insert into user(account,password) values("hhh","879");
insert into user(account,password) values("iii","987");
1)導入 MySQL -> HDFS
(1) 全表導入
bin/sqoop import \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306/testdb \
--username root \
--password root123 \
--table user \
--target-dir /input/import \
--num-mappers 1 \
--fields-terminated-by ","
bin/sqoop import \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306/testdb \
--username root \
-P \ //不使用明文指定數據庫鏈接密碼
--table user \
--target-dir /input/import \ //指定數據導入到HDFS上的目錄
--delete-target-dir \ //若是目標目錄已存在,則先刪除
--num-mappers 1 \ //指定使用導入數據的map個數
--fields-terminated-by "," //目標文件的分隔符
(2) query,where子句必須有$CONDITONS(固定寫法) 查詢導入方式
bin/sqoop import \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306/testdb \
--username root \
-P \
--query 'select id,account from user where account="fff" and $CONDITIONS' \
--target-dir /input/query \
-m 1 \
--delete-target-dir \
--fields-terminated-by "\t"
(3)增量導入
bin/sqoop import \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306/testdb \
--username root \
--password root123 \
--table user \
--target-dir /input/append \
-m 1 \
--fields-terminated-by " " \
--check-column id \
--incremental append \
--last-value 2
--append and --delete-target-dir can not be used together.
2)MySQL -> Hive
bin/sqoop import \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306/testdb \
--username root \
--password root123 \
--table user \
-m 1 \
--delete-target-dir \
--fields-terminated-by "\t" \
--hive-import \
--hive-overwrite \
--hive-database db01 \
--hive-table user
3).從HDFS、Hive表導出到Mysql
因爲hive表的數據庫和表其實就是HDFS上的目錄和文件,因此從Hive表導出數據就是從HDFS對應的目錄導出數據
先在mysql中建立表接收導出數據
create table hive2mysql(
deptno int,
deptname varchar(20),
address varchar(20)
);
bin/sqoop export \
--connect jdbc:mysql://bigdata.ibeifeng.com:3306/testdb \
--username root \
--password root123 \
--table hive2mysql \
--num-mappers 1 \
--export-dir /user/hive/warehouse/db01.db/dept \
--fields-terminated-by "\t"
4)能夠將Sqoop的命令選項寫在文件,經過【--options-file】指定文件,進行運行程序。
vim sqoop_script
export
--connect
jdbc:mysql://bigdata.ibeifeng.com:3306/testdb
--username
root
--password
root123
--table
hive2mysql
--num-mappers
1
--export-dir
/user/hive/warehouse/db01.db/dept
--fields-terminated-by
"\t"
$ bin/sqoop --options-file ~/sqoop_script
======================================
Hive 自定義函數函數
使用內置的函數沒法完成分析任務,那麼須要寫自定義函數
show functions; //查看自帶的全部的內置函數
desc function upper; //查看具體的某個函數的用法
desc function extended upper; //帶有具體案例
##分三類
## UDF 一進一出 處理原文件內容某些字段包含 [] ""
## UDAF 多進一出 sum() avg() max() min()
## UDTF 一進多出 ip -> 國家 省 市
UDF函數的開發
** 必須繼承UDF類
** 重寫evaluate函數 支持重載
** 必需要有返回類型,能夠返回null,可是返回類型不能爲void
** 建議使用Text/LongWritable
## 1.建立一個maven項目
## 2.修改pom.xml文件
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>0.13.1</version>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>0.13.1</version>
</dependency>
## 3.替換repository
## 4.包含hive的依賴的jar的repository
## 代碼實現(注意必須實現一個名爲evaluate的方法)
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
public class SalaryUDF extends UDF{
public Text evaluate(Text salaryText){
Text text = new Text();
//1.判斷salaryText是否爲null
if (salaryText == null) {
return null;
}
//2.判斷salaryText是否可轉換爲一個double類型
double salary = 0;
try {
salary = Double.valueOf(salaryText.toString());
} catch (NumberFormatException e) {
e.printStackTrace();
return null;
}
if (salary > 3000) {
text.set("大於3000的一組...");
return text;
}else if (salary <= 3000 && salary > 2000) {
text.set("小於等於3000而且大於2000的一組...");
return text;
}else {
text.set("小於等於2000的一組");
return text;
}
}
}
5.編寫使用UDF
1、編程
2、把程序到出爲jar包放到目標機器上去:
hive> add jar /home/beifeng/jars/lower.jar ;
3、建立臨時函數:
hive> CREATE TEMPORARY FUNCTION my_lower AS 'org.apache.hadoop.udf.Lower';
4、使用指定函數:
hive> show fuctions ;
hive> select my_lower(ename) from emp ;
Day04
內容:
1.離線分析平臺的應用
2.常見內置函數和自定義函數
3.壓縮
BI
1、Hive在離線分析平臺的應用
1.網站
電商網站:
京東、淘寶、一號店
遊戲網站
4399 17173 【遊戲推廣 遊戲排行榜 帳號交易】
旅遊網站
途牛 【報團,景點推薦,售票】
在線教育
學員的行爲(瀏覽課程,課程諮詢,購買課程)
2.統計分析指標 網站 KPI指標
基本指標:PV UV 獨立IP 二跳率 客戶轉化 會話時長
3.統計數據的來源
應用服務器的日誌文件
【擴展】
WEB服務器:只負責處理靜態網頁HTML,經過HTTP協議
應用服務器:負責 處理JSP,Servlet,負責業務邏輯頁面跳轉
【網站埋點技術:jsSDK JavaSDK】 【爬蟲】
4.日誌收集系統
Flume
Kafka
【擴展瞭解ELK】:日誌收集平臺
5.ETL過濾清洗
寫MR程序
過濾空值,髒數據
字段解析 補全
6.Hive統計分析 (思路) 【擴展瞭解:impala】
1).建立什麼樣的表
2).根據業務(7個:用戶模塊,訂單模塊,地域維度模塊),建立中間表,大表拆小表,統計分析模塊能夠減小數據量的反覆加載
【多維度分析:時間,地域維度,平臺,瀏覽器維度】
週期性統計分析:天 //粒度問題 最小的分析時間單位 /h 每小時
【案例】
1.建立二級分區表
//建立數據庫
create database db_track;
//建立二級分區表
create table tracklog(
id string,
url string,
referer string,
keyword string,
type string,
guid string,
pageId string,
moduleId string,
linkId string,
attachedInfo string,
sessionId string,
trackerU string,
trackerType string,
ip string,
trackerSrc string,
cookie string,
orderCode string,
trackTime string,
endUserId string,
firstLink string,
sessionViewNo string,
productId string,
curMerchantId string,
provinceId string,
cityId string,
fee string,
edmActivity string,
edmEmail string,
edmJobId string,
ieVersion string,
platform string,
internalKeyword string,
resultSum string,
currentPage string,
linkPosition string,
buttonPosition string
)
partitioned by (date string, hour string)
row format delimited fields terminated by '\t';
load data local inpath '/home/user01/tracklogs/20150828/2015082818' into table tracklog partition(date="20150828",hour="18");
load data local inpath '/home/user01/tracklogs/20150828/2015082819' into table tracklog partition(date="20150828",hour="19");
2.根據不一樣的統計分析業務需求建立中間表或者臨時表,以及結果表
//建立統計結果表
create table static_PVUV(
date string,
hour string,
pv int,
uv int
)
row format delimited fields terminated by '\t';
//統計分析並插入結果表中
insert overwrite table static_PVUV select date,hour,count(url),count(distinct guid) from tracklog where date="20150828" group by date,hour;
20150828 18 64972 23938
20150828 19 61162 22330
3)統計分析結果數據導出到mysql,以便於做圖形化展現
藉助SQOOP
create database daily_log;
use daily_log;
create table static_PVUV(
date int,
hour int,
pv int,
uv int
);
4)Sqoop導出數據
vim hive2mysql.opt
export
--connect
jdbc:mysql://bigdata.ibeifeng.com:3306/daily_log
--username
root
--password
root123
--table
static_PVUV
--input-fields-terminated-by
\t
--export-dir
/user/hive/warehouse/db_track.db/static_pvuv //在hive中使用desc formatted static_PVUV;來確認表的目錄所在
{$SQOOP_HOME}下
bin/sqoop --options-file /home/user01/hive2mysql.opt
+----------+------+-------+-------+
| date | hour | pv | uv |
+----------+------+-------+-------+
| 20150828 | 19 | 61162 | 22330 |
| 20150828 | 18 | 64972 | 23938 |
+----------+------+-------+-------+
5)使用shell腳本結合定時腳本週期性自動執行
#!/bin/sh
##執行環境變量,以便於腳本中可使用。「.」的後面有一個空格,表明執行這個腳本文件
. /etc/profile
# 定義Hive目錄
HIVE_DIR=/opt/modules/cdh/hive-0.13.1-cdh5.3.6
# 定義數據源目錄
DATA_LOG=/home/user01/tracklogs
# 定義昨天的日期,按照固定格式,可使用echo $(date --date="1 day ago" +%Y%m%d)嘗試
YESTERDAY=$(date --date="1 day ago" +%Y%m%d)
# for循環中do...done中間的循環體執行的次數等於in後面元素的個數
# 在咱們這裏,hql文件被調用了2次
for LOG_DAY in `ls $DATA_LOG/$YESTERDAY`
do
#分別取出文件名中的日期和小時
DATE=${LOG_DAY:0:8}
HOUR=${LOG_DAY:8:2}
#在測試時,可使用echo打印下面命令
$HIVE_DIR/bin/hive -e "load data local inpath '$DATA_LOG/$YESTERDAY/${DATE}${HOUR}' into table db_log.track_log partition (date='$DATE',hour='$HOUR')"
done
===crontable 定時任務
30 0 * * * /bin/sh /home/user01/loaddata.sh
2、Hive的內置函數
1.查看內置函數的相關指令
查看全部的內置函數:
show functions;
顯示函數的描述信息
desc function substr;
顯示函數的擴展描述信息
desc function extended substr;
2.內置函數分類
Hive的函數
數學函數
round -四捨五入
select round(12.3456, 2), round(12.3456, 0), round(12.3456, -1), round(12.3456, -2);
ceil --向上取整
select ceil(12.3456)
floor --向下取整
select floor(12.3456)
字符函數
lower --將全部字符轉換成小寫
upper() --將全部字符轉換成大寫
select lower('Hello World'),upper('Hello World');
length --字符傳串長度
concat --鏈接字符串
select concat(empname,salary) form emp ;
substr --字符串截取
select substr(birthday,1,4) from emp;
trim --去空格
lpad --左填充 第一個表明被填充的對象,第二個表明填充以後的總位數,第三個表明用什麼填充
rpad --右填充
select lpad('Hello',10,'lilei,'),rpad('Hello',10,'lilei');
日期函數
unix_timestamp --將時間轉化爲時間戳
select unix_timestamp('2017-03-13 15:22:30');
to_date --抽取date或者日期中的date部分
select to_date('2017-03-13 15:22:30');
year
month
day
select year('2017-03-13 15:22:30'),month('2017-03-13 15:22:30'),day('2017-03-13 15:22:30');
weekofyear --指定的日期輸入一年中的哪一週
select weekofyear('2017-03-13 15:22:30');
datediff --指定的兩個日期之間的相差的時間
select atediff('2017-03-13 15:22:30','2016-03-13 15:22:30');
date_add --指定的日期加上一個數字的日期
date_sub --指定的日期減去一個數字的日期
select date_add('2017-03-13 15:22:30',2),date_sub('2017-03-13 15:22:30',2);
類型轉換函數
cast
select cast(1422/1000 as int) from emp;
條件函數
coalesce -c從左到右返回第一個不爲null的值
case a when b then c [when d then e]* [else f] end
應用案例:
漲工資,總裁+1000,經理+800,其餘員工+400
select empname,empjob,salary,case empjob when'PRESIDENT' then salary+1000 when 'MANAGER' then salary+800 else salary+400 end form emp;
特殊函數:
窗口函數:lead lag FIRST_VALUE
分析函數:RANK ROW_NUMBER
3、四大排序
1、order by //能夠指定desc 降序 asc 升序
order by會對輸入作全局排序,所以只有一個Reducer(多個Reducer沒法保證全局有序),然而只有一個Reducer,會致使當輸入規模較大時,消耗較長的計算時間。
mapreduce 默認的分區算法hash 取模
a c e reduce-0
b d f reduce-0
a b c d e f
e.g.1:
create table temperature(
year int,
temper float
)
row format delimited fields terminated by '\t';
temperature.year temperature.temper
2008 32.0
2008 21.0
2008 31.5
2008 17.0
2013 34.0
2015 32.0
2015 33.0
2015 15.9
2015 31.0
2015 19.9
2015 27.0
2016 23.0
2016 39.9
2016 32.0
2.sort by
sort by不是全局排序,其在數據進入reducer前完成排序,所以,若是用sort by進行排序,而且設置mapred.reduce.tasks>1,則sort by只會保證每一個reducer的輸出有序,並不保證全局有序。sort by不一樣於order by,它不受Hive.mapred.mode屬性的影響,sort by的數據只能保證在同一個reduce中的數據能夠按指定字段排序。使用sort by你能夠指定執行的reduce個數(經過set mapred.reduce.tasks=n來指定),對輸出的數據再執行歸併排序,便可獲得所有結果。
/設置reduce個數爲3;
set mapred.reduce.tasks=3;
//查詢這次任務中reduce的個數;
set mapred.reduce.tasks;
insert overwrite local directory '/home/user01/sort' row format delimited fields terminated by '\t' select * from temperature sort by year;
[user01@hadoop sort]$ ls
000000_0 000001_0 000002_0
[user01@hadoop sort]$ cat 000000_0
2008 31.5
2008 21.0
2015 31.0
2015 32.0
2015 33.0
2016 23.0
[user01@hadoop sort]$ cat 000001_0
2008 17.0
2013 34.0
2015 19.9
2015 15.9
2016 39.9
2016 32.0
[user01@hadoop sort]$ cat 000002_0
2008 32.0
2015 27.0
3.distribute by
distribute by是控制在map端如何拆分數據給reduce端的。hive會根據distribute by後面列,對應reduce的個數進行分發,默認是採用hash算法。sort by爲每一個reduce產生一個排序文件。在有些狀況下,你須要控制某個特定行應該到哪一個reducer,這一般是爲了進行後續的彙集操做。distribute by恰好能夠作這件事。所以,distribute by常常和sort by配合使用。
//根據年份和睦溫對氣象數據進行排序,以確保全部具備相同年份的行最終都在一個reducer分區中
注:Distribute by和sort by的使用場景
1.Map輸出的文件大小不均。
2.Reduce輸出文件大小不均。
3.小文件過多。
4.文件超大。
$ cat distribute/000000_0
2016,23.0
2016,39.9
2016,32.0
2013,34.0
$ cat distribute/000001_0
2008,32.0
2008,21.0
2008,31.5
2008,17.0
$ cat distribute/000002_0
2015,31.0
2015,19.9
2015,27.0
2015,32.0
2015,33.0
2015,15.9
//兩者結合使用
select * from temperature distribute by year sort by year asc, temper desc;
2013 34.0
2016 39.9
2016 32.0
2016 23.0
2008 32.0
2008 31.5
2008 21.0
2008 17.0
2015 33.0
2015 32.0
2015 31.0
2015 27.0
2015 19.9
2015 15.9
4.cluster by
cluster by除了具備distribute by的功能外還兼具sort by的功能。可是排序只能是倒敘排序,不能指定排序規則爲ASC或
者DESC。
select * from cluster by year;
4、分組排名
TOPN
row number
說明:
row_number() over ([partition col1] [order by col2])
rank() over ([partition col1] [order by col2])
dense_rank() over ([partition col1] [order by col2])
它們都是根據col1字段分組,而後對col2字段進行排序,對排序後的每行生成一個行號,這個行號從1開始遞增
col1、col2均可以是多個字段,用‘,‘分隔
區別:
1)row_number:無論col2字段的值是否相等,行號一直遞增,好比:有兩條記錄的值相等,但一個是第一,一個是第二
2)rank:上下兩條記錄的col2相等時,記錄的行號是同樣的,但下一個col2值的行號遞增N(N是重複的次數),好比:有兩條並列第一,下一個是第三,沒有第二
3)dense_rank:上下兩條記錄的col2相等時,下一個col2值的行號遞增1,好比:有兩條並列第一,下一個是第二
select empname,empjob,salary,deptno,row_number() over(partition by deptno order by salary asc ) rank from emp;
empname empjob salary deptno rank
MILLER CLERK 1300.0 10 1
CLARK MANAGER 2450.0 10 2
KING PRESIDENT 5000.0 10 3
SMITH CLERK 800.0 20 1
ADAMS CLERK 1100.0 20 2
JONES MANAGER 2975.0 20 3
SCOTT ANALYST 3000.0 20 4
FORD ANALYST 3000.0 20 5
JAMES CLERK 950.0 30 1
MARTIN SALESMAN 1250.0 30 2
WARD SALESMAN 1250.0 30 3
TURNER SALESMAN 1500.0 30 4
ALLEN SALESMAN 1600.0 30 5
BLAKE MANAGER 2850.0 30 6
//測試原數據
Hive TopN
a chinese 98
a english 90
a math 90
d chinese 88
c english 82
c math 98
b math 79
b chinese 79
b english 79
z english 90
z math 89
z chinese 80
e math 99
e english 87
d english 90
create table t(name string, sub string, score int) row format delimited fields terminated by '\t';
load data local inpath "/home/user01/grades.txt" into table t;
//爲每一個學生的各門功課成績排名
1、row_number
select *,row_number() over (partition by name order by score desc) as rank from t;
t.name t.sub t.score rank
a chinese 98 1
a english 90 2
a math 90 3
b chinese 79 1
b english 79 2
b math 79 3
c math 98 1
c english 82 2
d english 90 1
d chinese 88 2
e math 99 1
e english 87 2
z english 90 1
z math 89 2
z chinese 80 3
2.rank //排序字段相同的記錄使用相同的排名,下一個從值的行號遞增N(N是重複的次數),好比:有兩條並列第一,下一個是第三,沒有第二
select *,rank() over (partition by name order by score asc) as rank from t;
t.name t.sub t.score rank
a english 90 1
a math 90 1
a chinese 98 3
b chinese 79 1
b english 79 1
b math 79 1
c english 82 1
c math 98 2
d chinese 88 1
d english 90 2
e english 87 1
e math 99 2
z chinese 80 1
z math 89 2
z english 90 3
3、dense_rank //排序字段相同的記錄使用相同的排名,下一個值的行號遞增1,以下:a的english和math並列第一,下一個chinese是第三,沒有第二,b的三門都同樣
select *,dense_rank() over (partition by name order by score asc) as rank from t;
t.name t.sub t.score rank
a english 90 1
a math 90 1
a chinese 98 2
b chinese 79 1
b english 79 1
b math 79 1
c english 82 1
c math 98 2
d chinese 88 1
d english 90 2
e english 87 1
e math 99 2
z chinese 80 1
z math 89 2
z english 90 3
業務實例:
統計每一個學科的前二名
select * from (select *, row_number() over(partition by name order by score desc) as rank from t )t where rank <=2;
select *,row_number() over () as rank from t rank <=3;
select area, barnd, yuan, row_number() over (partition by area order by yuan desc) as rank from order where rank <=3;
各地區熱門商品統計
按地區 分組 再按各個商品的銷量進行降序排名
北京 iphone7 70000 1
北京 xiaomi5 60000 2
北京 mate9 50000 3
北京 手機膜 40000 4
...
上海 xiaomi5 70000 1
上海 iphone7 60000 2
上海 mate9 50000 3
上海 手機膜 40000 4
..
5、Hive的數據壓縮
1.Hive使用的文件格式
: SEQUENCEFILE//序列化 #二進制格式,沒法使用cat查看
| TEXTFILE -- (Default, depending on hive.default.fileformat configuration)
| RCFILE -- (Note: Available in Hive 0.6.0 and later) Row存儲 Columnar字段也就是列
| ORC -- (Note: Available in Hive 0.11.0 and later) O optimized 優化
| PARQUET -- (Note: Available in Hive 0.13.0 and later)
| AVRO -- (Note: Available in Hive 0.14.0 and later)
能夠將默認TEXTFILE 文件格式的表映射完成以後,另外保存成其餘格式ORC PARQUE
create table if not exists file_text(
t_time string,
t_url string,
t_uuid string,
t_refered_url string,
t_ip string,
t_user string,
t_city string
)
row format delimited fields terminated by '\t'
stored as textfile;
load data local inpath '/home/user01/page_views.data' into table file_text;
//默認的TEXTFILE格式大小
dfs -du -s -h /user/hive/warehouse/db01.db/file_text;
18.1 M 18.1 M /user/hive/warehouse/db01.db/file_text
//存儲爲ORC格式
create table if not exists file_orc row format delimited fields terminated by '\t' stored as ORC as select * from file_text;
dfs -du -s -h /user/hive/warehouse/db01.db/file_orc;
2.6 M 2.6 M /user/hive/warehouse/db01.db/file_orc
//存儲爲parquet格式
create table if not exists file_parquet row format delimited fields terminated by '\t' stored as PARQUET as select * from file_text;
dfs -du -s -h /user/hive/warehouse/db01.db/file_parquet;
13.1 M 13.1 M /user/hive/warehouse/db01.db/file_parquet
2.壓縮
減小磁盤存儲壓力,負載
減小IO負載
1).首先,要保證hadoop是支持壓縮
檢查是否支持壓縮算法
$ bin/hadoop checknative
Native library checking:
hadoop: false
zlib: false
snappy: false
lz4: false
bzip2: false
openssl: false
snappy 壓縮比和速度至關於適中的
2)編譯hadoop源碼:mvn package -Pdist,native,docs -DskipTests -Dtar -Drequire.snappy
3)##替換$HADOOP_HOME/lib/native
$ tar -zxf cdh5.3.6-snappy-lib-natirve.tar.gz -C ./
再次檢查 $ bin/hadoop checknative
Native library checking:
hadoop: true /opt/modules/cdh/hadoop-2.5.0-cdh5.3.6/lib/native/libhadoop.so.1.0.0
zlib: true /lib64/libz.so.1
snappy: true /opt/modules/cdh/hadoop-2.5.0-cdh5.3.6/lib/native/libsnappy.so.1
lz4: true revision:99
bzip2: true /lib64/libbz2.so.1
openssl: true /usr/lib64/libcrypto.so
啓動dfs,yarn,historyserver,而後提交一個job
$ bin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0-cdh5.3.6.jar pi 1 2
完成以後,web界面查看完成這個任務的配置
mapreduce.map.output.compress false
mapreduce.map.output.compress.codec org.apache.hadoop.io.compress.DefaultCodec
4)配置mapred-site.xml,在原有的下方增長以下內容
<property>
<name>mapreduce.map.output.compress</name>
<value>true</value>
</property>
<property>
<name>mapreduce.map.output.compress.codec </name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
結束全部進程,從新啓動全部進程dfs,yarn,historyserver,再提交一個job
$ bin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0-cdh5.3.6.jar pi 3 5
完成以後,web界面從新查看完成這個任務的配置
mapreduce.map.output.compress true job.xml ⬅ mapred-site.xml
mapreduce.map.output.compress.codec org.apache.hadoop.io.compress.SnappyCodec
/啓用壓縮snappy+存儲爲ORC格式
方式一 在MapReduce的shuffle階段啓用壓縮
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org apache.hadoop.io.compress.SnappyCodec;
create table if not exists file_orc_snappy(
t_time string,
t_url string,
t_uuid string,
t_refered_url string,
t_ip string,
t_user string,
t_city string
)
row format delimited fields terminated by '\t'
stored as ORC
tblproperties("orc.compression"="Snappy");
insert into table file_orc_snappy select * from file_text;
方式二:對reduce輸出的結果文件進行壓縮
set mapreduce.output.fileoutputformat.compress=true;
set mapreduce.output.fileoutputformat.compress.codec=org apache.hadoop.io.compress.SnappyCodec;
create table if not exists file_orc_snappy2(
t_time string,
t_url string,
t_uuid string,
t_refered_url string,
t_ip string,
t_user string,
t_city string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compression"="Snappy");
insert into table file_orc_snappy2 select * from file_text;
Day05
1.【案例:結合正則表達式 映射特殊格式的表格】
2.UD函數
3.Hive優化
4.案例
"27.38.5.159" "-" "31/Aug/2015:00:04:37 +0800" "GET /course/view.php?id=27 HTTP/1.1" "303" "440" - "http://chao.com/user.php?act=mycourse" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" "-" "learn.ibeifeng.com"
(\"[^ ]\") (\"-[^ ]\")
^ 一個字符串的開始
$ 一個字符串的結束
"^The" "There" "The cat"
$e 以字符e結尾的字符串
一個或者一序列字符重複出現的次數
* 0次或屢次 {0,}
+ 1次或屢次 {1,}
? 至多出現一次 0次或者1次 {0,1}
{}使用範圍,用大括號,表示重複出現次數的範圍
「ab{2}」 表示一個字符串有一個a跟着2個b
ab{2,4}
[] 表示某些字符容許在一個字符串中某一個特定位置出現
^[a-zA-Z]:標表示一個以字母開頭的字符串
| 表示「或」操做
hi|hello 一個字符串裏有"hi"或者"hello"
(b|cd)ef 表示"bef"或"cdef"
[^] 表示不但願出現的字符
$ () "" 但願匹配這些字符的時候,應該在特殊字符前面加轉義字符"\"
(\"[^ ]*\") (\"-|[^ ]*\") (\"[^\]]*\") (\"[^\]]*\") (\"[0-9]*\") (\"[0-9]*\") (-|[^ ]*) (\"[^ ]*\") (\"[^\"]*\") (\"-|[^ ]*\") (\"[^ ]*\")
"27.38.5.159" "-" "31/Aug/2015:00:04:37 +0800" "GET /course/view.php?id=27 HTTP/1.1" "303" "440" - "http://chao.com/user.php?act=mycourse" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" "-" "learn.ibeifeng.com"
drop table if exists apachelog;
CREATE TABLE apachelog (
remote_addr string,
remote_user string,
time_local string,
request string,
status string,
body_bytes_set string,
request_body string,
http_referer string,
http_user_agent string,
http_x_forwarded_for string,
host string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "(\"[^ ]*\") (\"-|[^ ]*\") (\"[^\]]*\") (\"[^\]]*\") (\"[0-9]*\") (\"[0-9]*\") (-|[^ ]*) (\"[^ ]*\") (\"[^\"]*\") (\"-|[^ ]*\") (\"[^ ]*\")"
)
STORED AS TEXTFILE;
Eclipse 開發UDF函數
1.替換本地repository目錄
${MAVEN_HOME}/conf/settings.xml
<localRepository>~\.m2\repository</localRepository>
$tar -zxf repository.tar.gz -C ~\.m2\repository
2.Eclispe windows -> prefereneces -> [鍵入maven] ->替換爲本身安裝的maven3.0.5 -> User settings -> Reindex
3.原來的maven工程中的porm.xml 添加兩組和hive相關的<dependency>
4.在項目名稱上右鍵-> Maven -> Update Project -> force update ...
注意順序:
先替換repository,接下來修改porm.xml或者建立maven工程
不然,會自動下載jar文件,若是一旦網絡出錯,jar文件可能就是損壞的,這個時候須要先將出錯文件刪除掉再從新下,所以不推薦本身去下載
建立臨時函數的方式一:
//將導出的jar文件加入到hive的calss path
add jar /home/user01/RemoveQuote.jar;
//建立臨時函數 removequote--能夠自定義 可是必須指定對應的帶包名的主類
CREATE TEMPORARY FUNCTION removequote as 'hive.RemoveQuoteUDF';
//查看建立的函數是否存在
show functions;
//將導出的jar文件加入到hive的calss path
add jar /home/user01/TimeFormat.jar;
Added /home/user01/TimeFormat.jar to class path
Added resource: /home/user01/TimeFormat.jar
//建立臨時函數 注意:臨時函數名稱不能和內置函數名相同
CREATE TEMPORARY FUNCTION TimeFormat as 'hive.TimeFormatUDF';
建立臨時函數的方式二:
在hive中使用(第二種方式)
將linux中的jar包上傳到自定義位置的hdfs的文件系統
hive (mydb)> create [temporary] function my_lower as 'com.ibeifeng.bigdata.test.hive.udf.Lower' using jar 'hdfs/path';
注:關於'hdfs/path' :
hdfs://hostname:8020/自定義的文件位置
【對比】
未做任何處理
select remote_addr,time_local,request from apachelog_extract limit 2;
"27.38.5.159" "31/Aug/2015:00:04:37 +0800" "GET /course/view.php?id=27 HTTP/1.1"
"27.38.5.159" "31/Aug/2015:00:04:37 +0800" "GET /login/index.php HTTP/1.1"
//使用removequot臨時函數去除字段雙引號
select removequote(remote_addr) remote_addr,removequote(time_local) time_local,request from apachelog_extract limit 2
27.38.5.159 31/Aug/2015:00:04:37 +0800 "GET /course/view.php?id=27 HTTP/1.1"
27.38.5.159 31/Aug/2015:00:04:37 +0800 "GET /login/index.php HTTP/1.1"
//使用removequote和timeformat,同時進行去除雙引號和格式化時間
select removequote(remote_addr) remote_addr,timeformat(time_local) time_local,request from apachelog_extract limit 2;
27.38.5.159 2015-08-31 00:04:37 "GET /course/view.php?id=27 HTTP/1.1"
27.38.5.159 2015-08-31 00:04:37 "GET /login/index.php HTTP/1.1"
Hive優化
1. fetch task任務不走MapReduce,能夠在hive配置文件中設置最大化和最小化fetch task任務;一般在使用hiveserver2時調整爲more;
設置參數的優先級:在命令行或者代碼設置參數 > hive-site.xml>hive-default.xml
set hive.fetch.task.conversion=more; //單次交互模式下有效,
bin/hive --hiveconf hive.fetch.task.conversion=more
上面的兩種方法均可以開啓了Fetch任務,可是都是臨時起做用的;若是你想一直啓用這個功能,能夠在${HIVE_HOME}/conf/hive-site.xml裏面加入如下配置:
<property>
<name>hive.fetch.task.conversion</name>
<value>more</value>
<description>
Some select queries can be converted to single FETCH task
minimizing latency.Currently the query should be single
sourced not having any subquery and should not have
any aggregations or distincts (which incurrs RS),
lateral views and joins.
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns)
</description>
</property>
2. strict mode:嚴格模式設置,嚴格模式下將會限制一些查詢操做
文件格式,ORC PARQUET 等
分區表
select 查詢不加where過濾條件,不會執行
開啓嚴格模式
hive提供的嚴格模式,禁止3種狀況下的查詢模式。
a:當表爲分區表時,where字句後沒有分區字段和限制時,不容許執行。
b:當使用order by語句時,必須使用limit字段,由於order by 只會產生一個reduce任務。
c:限制笛卡爾積的查詢。sql語句不加where不會執行
<property>
<name>hive.mapred.mode</name>
<value>nonstrict</value>
<description>The mode in which the Hive operations are being performed.
In strict mode, some risky queries are not allowed to run. They include:
Cartesian Product.
No partition being picked up for a query.
Comparing bigints and strings.
Comparing bigints and doubles.
Orderby without limit.
</description>
</property>
3. MapReduce過程的map、shuffle、reduce端的snappy壓縮
須要先替換hadoop的native本地包開啓壓縮
在mapred-site.xml文件設置啓用壓縮及壓縮編碼
在執行SQL執行時設置啓用壓縮和指定壓縮編碼
set mapreduce.output.fileoutputformat.compress=true;
set mapreduce.output.fileoutputformat.compress.codec=org apache.hadoop.io.compress.SnappyCodec;
4. 大表拆分紅子表,提取中間結果集,減小每次加載數據
多維度分析,多個分析模塊
每一個分析模塊涉及字段不同,並且並非表的所有字段
5. 分區表及外部表
設計二級分區表(一級字段爲天,二級字段設置小時)
建立的的是外部表,建立表時直接指定數據所在目錄便可,不用再用load加載數據
6. 設置map和reduce個數:默認狀況下一個塊對應一個map任務,map數據咱們通常不去調整,reduce個數根據reduce處理的數據量大小進行適當調整
體現「分而治之」的思想
set mapred.reduce.tasks=3;
7. 優化sql語句,如先過濾再join,先分組再作distinct
8. 並行執行:一個sql有1、2、3 三個job,其中1、2job是在join後再與3job結果進行join,那麼1、2job在join同時3job能夠同時並行執行
分佈式並行化
set hive.exec.parallel=true;
set hive.exec.parallel.thread.number=8;
eg:
select num
from
(select count(city) as num from city
union all
select count(province) as num from province
)tmp;
9. JVM重用:一個job可能有多個map reduce任務,每一個任務會開啓一個JVM虛擬機,默認狀況下一個任務對應一個JVM,任務運行完JVM即銷燬,咱們能夠設置JVM重用參數,通常不超過5個,這樣一個JVM內能夠連續運行多個任務
JVM重用是Hadoop調優參數的內容,對Hive的性能具備很是大的影響,特別是對於很難避免小文件的場景或者task特別多的場景,這類場景大多數執行時間都很短。hadoop默認配置是使用派生JVM來執行map和reduce任務的,這是jvm的啓動過程可能會形成至關大的開銷,尤爲是執行的job包含有成千上萬個task任務的狀況。
JVM重用可使得JVM實例在同一個JOB中從新使用N次,N的值能夠在Hadoop的mapre-site.xml文件中進行設置(建議參考5~10)
mapred.job.reuse.jvm.num.tasks
也可在hive的執行設置:
***set mapred.job.reuse.jvm.num.tasks=10;
10. 推測執行:例如一個MapReduce應用有10個任務(map 及reduce),其中9個任務已經完成,那麼application Master會在另外啓動一個相同的任務來運行未完成的那個,最後哪一個先運行完成就把另外一個kill掉
啓用speculative最大的好處是,一個map執行的時候,系統會在其餘空閒的服務器上啓動相同的map來同時運行,哪一個運行的快就使用哪一個的結果,另外一個運行慢的在有告終果以後就會被kill。
mapred.map.tasks.speculative.execution=true
mapred.reduce.atasks.specultive.execution=true
hive.mapred.reduce.tasks.speculative.execution=true;
11.查看執行計劃
***explain [extended] hql
eg:
explain select no,count(*) from testudf group by no;
explain extended select no,count(*) from testudf group by no;
hive入門學習:explain執行計劃的理解 - HAHA的專欄 - 博客頻道 - CSDN.NET
http://blog.csdn.net/liyaohhh/article/details/50697076
數據傾斜
對於普通的join操做,會在map端根據key的hash值,shuffle到某一個reduce上去,在reduce端作join鏈接操做,內存中緩存join左邊的表,遍歷右邊的表,依次作join操做。因此在作join操做時候,將數據量多的表放在join的右邊。
當數據量比較大,而且key分佈不均勻,大量的key都shuffle到一個reduce上了,就出現了數據的傾斜。
常見的數據傾斜出如今group by和join..on..語句中。
join(數據傾斜)
在進行兩個表join的過程當中,因爲hive都是從左向右執行,要注意講小表在前,大表在後(小表會先進行緩存)。
key 河南 value 考生
map/reduce程序執行時,reduce節點大部分執行完畢,可是有一個或者幾個reduce節點運行很慢,致使整個程序的處理時間很長,這是由於某一個key的條數比其餘key多不少(有時是百倍或者千倍之多),這條key所在的reduce節點所處理的數據量比其餘節點就大不少,從而致使某幾個節點遲遲運行不完,此稱之爲數據傾斜。
hive在跑數據時常常會出現數據傾斜的狀況,使的做業常常reduce完成在99%後一直卡住,最後的1%花了幾個小時都沒跑完,這種狀況就極可能是數據傾斜的緣由,
hive.groupby.skewindata=true;
若是是group by過程出現傾斜應將此項設置true。
hive.optimize.skewjion=true;
若是是join 過程當中出現傾斜應將此項設置爲true
不影響結果能夠考慮過濾空值
能夠在空值前面加隨機散列
4.1Map-side Join
mapJoin的主要意思就是,當連接的兩個表是一個比較小的表和一個特別大的表的時候,咱們把比較小的table直接放到內存中去,而後再對比較大的表格進行map操做。join就發生在map操做的時候,每當掃描一個大的table中的數據,就要去去查看小表的數據,哪條與之相符,繼而進行鏈接。這裏的join並不會涉及reduce操做。map端join的優點就是在於沒有shuffle,真好。在實際的應用中,咱們這樣設置:
***1. set hive.auto.convert.join=true;
這樣設置,hive就會自動的識別比較小的表,繼而用mapJoin來實現兩個表的聯合。看看下面的兩個表格的鏈接。
這裏的第一句話就是運行本地的map join任務,繼而轉存文件到XXX.hashtable下面,在給這個文件裏面上傳一個文件進行map join,以後才運行了MR代碼去運行計數任務。說白了,在本質上mapjoin根本就沒有運行MR進程,僅僅是在內存就進行了兩個表的聯合。
hive.optimize.skewjoin=true; 若是是join過程出現傾斜應該設置爲true
此時會將join語句轉化爲兩個mapreduce任務,第一個會給jion字段加隨機散列
set hive.skewjoin.key=100000; 這個是join的鍵對應的記錄條數超過這個值則會進行優化。
mapjoin使用場景
1.關聯操做中有一張表很是小
2.不等值的連接操做
自動執行
set hive.auto.convert.join=true;
hive.mapjoin.smalltable.filesize=25;默認值是25mb
手動執行 A爲小表
select /*+mapjoin(A)*/ f.a,f.b from A t join B f on(f.a==t.a)
hive入門學習:join的三種優化方式 - HAHA的專欄 - 博客頻道 - CSDN.NET
http://blog.csdn.net/liyaohhh/article/details/50697519
4.2Reduce-side Join
***hive join操做默認使用的就是reduce join
Reduce-side Join原理上要簡單得多,它也不能保證相同key但分散在不一樣dataset中的數據可以進入同一個Mapper,整個數據集合的排序在Mapper以後的shuffle過程當中完成。相對於Map-side Join,它不須要每一個Mapper都去讀取全部的dataset,這是好處,但也有壞處,即這樣一來Mapper以後須要排序的數據集合會很是大,所以shuffle階段的效率要低於Map-side Join。
***reduce side join是一種最簡單的join方式,其主要思想以下:
在map階段,map函數同時讀取兩個文件File1和File2,爲了區分兩種來源的key/value數據對,對每條數據打一個標籤(tag),好比:tag=0表示來自文件File1,tag=2表示來自文件File2。即:map階段的主要任務是對不一樣文件中的數據打標籤。
在reduce階段,reduce函數獲取key相同的來自File1和File2文件的value list, 而後對於同一個key,對File1和File2中的數據進行join(笛卡爾乘積)。即:reduce階段進行實際的鏈接操做。
***4.3 SMB Join(sort merge bucket)
SMB 存在的目的主要是爲了解決大表與大表間的 Join 問題,分桶其實就是把大表化成了「小表」,而後 Map-Side Join 解決之,這是典型的分而治之的思想。
對於每個表(table)或者分區, Hive能夠進一步組織成桶,也就是說桶是更爲細粒度的數據範圍劃分。Hive也是 針對某一列進行桶的組織。Hive採用對列值哈希,而後除以桶的個數求餘的方式決定該條記錄存放在哪一個桶當中。
smb是sort merge bucket操做,首先進行排序,繼而合併,而後放到所對應的bucket中去,bucket是hive中和分區表相似的技術,就是按照key進行hash,相同的hash值都放到相同的buck中去。再進行兩個表聯合的時候。咱們首先進行分桶,在join會大幅度的對性能進行優化。也就是說,在進行聯合的時候,是table1中的一小部分和table2中的一小部分進行聯合,table聯合都是等值鏈接,相同的key都放到了同一個bucket中去了,那麼在聯合的時候就會大幅度的減少無關項的掃描。
分桶:
set hive.enforce.bucketing=true;
set hive.enforce.sorting=true;
表優化數據目標:相同數據儘可能彙集在一塊兒
兩個表以相同方式劃分捅。
兩個表的桶個數是倍數關係。
create table ordertab(cid int,price,float)clustered by(cid) into 32 buckets;
create table customer(id int,first string)clustered by(id) into 32 buckets;
select price from ordertab t join customer s on t.cid=s.id
set hive.optimize.bucketmapjoin=true;
set hive.optimize.bucketmapjoin.sortedmeger=true;
set hive.input.formtat=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
[當心得,小體會]
hive (db01)> set hive.exec.mode.local.auto=true;
hive (db01)> set hive.exec.mode.local.auto;
hive.exec.mode.local.auto=true
bin/hive --hiveconf hive.fetch.task.conversion=more;
bin/hive --hiveconf hive.exec.mode.local.auto=true;
Hive遠程模式
生產環境下用
存放元數據的MySQL數據庫服務器和Hive服務器不在同一臺上,甚至放在不一樣的操做系統上。
【問題】
如何確保元數據的安全?
1.按期備份Mysql
2.搭建高可用的Mysql集羣
修改hive-site.xml
<property>
<name>hive.metastore.uris</name>
<value>thrift://[hostname]:9083</value>
<description>Thrift URI for the remote metastore. Used by metastore client to connect to remote metastore.</description>
</property>
開啓metastore服務或者進程
$ bin/hive --service metastore &
$ bin/hive --service hiveserver2 & //beeline jdbc
檢測是否啓動(查看端口號)
netstat -antp | grep 9083
netstat -antp | grep 100000
結束進程
使用上述查看端口對應的進程的命令找出pid,而後使用kill -9 pid
*****設置成遠程模式以後必須保證先啓動metastore服務或者進程,以後才能進行bin/hive
日誌分析【擴展練習-重要的是理解思路】
1) UV:Unique Visited--- count(distinct guid)
訪問您網站的一臺電腦客戶端爲一個訪客。00:00-24:00內相同的客戶端只被計算一次。
2) PV:Page View--- count(url)
即頁面瀏覽量或點擊量,用戶每次刷新即被計算一次。
3) 登陸人數:
登陸網站訪問的人數[會員],endUserId有值的數量
4) 訪客人數:
沒有登陸訪問的人數,endUserId爲空的數量
5) 平均訪問時長:
訪客平均在網站停留的時間
trackTime --> max - min
6) 二跳率: pv>1的訪問量/總訪問量
平均瀏覽2個頁面及以上(pv>1)的用戶數 / 用戶總數
二跳率的概念是當網站頁面展開後,用戶在頁面上產生的首次點擊被稱爲「二跳」,二跳的次數即爲「二跳量」。二跳量與瀏覽量的比值稱爲頁面的二跳率。
7) 獨立IP:---count(distinct ip)
獨立IP表示,擁有特定惟一IP地址的計算機訪問您的網站的次數,由於這種統計方式比較容易實現,具備較高的真實性,因此成爲大多數機構衡量網站流量的重要指標。好比你是ADSL撥號上網的,你撥一次號都自動分配一個ip,這樣你進入了本站,那就算一個ip,當你斷線了而沒清理cookies,以後又撥 了一次號,又自動分配到一個ip,你再進來了本站,那麼又統計到一個ip,可是UV(獨立訪客)沒有變,由於2次都是你進入了本站。
思路分析:
第一步:建立臨時表1:session_info_tmp1
可根據sessionid和guid分組(同一個sessionid也確定是同一個guid),獲取如下字段信息:
sessionid:用戶session號
guid:用戶全局惟一id號
endUserId:會員id(登錄則有,不登陸則是空)
使用max(endUserId)能夠獲取非空的字段值(非空字符串>空字符串)
pv:經過count(url)獲取
stay_time:經過最大的tracktime-最小 的tracktime得到
min_trackTime:經過分組中最小tracktime獲取
ip:同一個sessionId都應該有同一個ip,經過max(ip)獲取
provinceId:同一個sessionId都應該有同一個provinceId,經過max(provinceId)獲取
注:因爲使用sessionId分組,trackerU、landing_url、landing_url_ref這三個字段都不必定是一個,因此在臨時表1中不加入此三字段,然而這三個字段是會話信息表中要求實現的,因此建立臨時表2
第二步:建立臨時表2:session_info_tmp2
經過track_log獲取全部sessionId、tracktime、trackerU、landing_url、landing_url_ref這五個字段,sessionId、tracktime這兩個字段都是用來join的時候使用。
trackerU:渠道id
landing_url:首次登錄的url
landing_url_ref:首次登錄的渠道url(從哪一個url而來)
第三步:join臨時表1和臨時表2,獲得會話跟蹤表session_info
因爲在一次會話期間可能產生多個trackerU、landing_url、landing_url_ref的值,而咱們實際須要的是這個session一開始的渠道id,在臨時表1中按sessionId分組保留每一個分組中最小的tracktime,關聯臨時表2中的tracktime,從而取出表2中每一個分組中初始tracktime對應的trackerU、landing_url、landing_url_ref的值。
create database db_track;
create table track_log(
id string,
url string,
referer string, //外部連接
keyword string,
type string,
guid string,
pageId string,
moduleId string,
linkId string,
attachedInfo string,
sessionId string,
trackerU string,
trackerType string,
ip string,
trackerSrc string,
cookie string,
orderCode string,
trackTime string,
endUserId string,
firstLink string,
sessionViewNo string,
productId string,
curMerchantId string,
provinceId string,
cityId string,
fee string,
edmActivity string,
edmEmail string,
edmJobId string,
ieVersion string,
platform string,
internalKeyword string,
resultSum string,
currentPage string,
linkPosition string,
buttonPosition string
)
partitioned by (date string,hour string)
row format delimited fields terminated by '\t';
load data local inpath '/home/user01/Downloads/2015082818' into table track_log partition (date="20150828",hour="18");
load data local inpath '/home/user01/Downloads/2015082819' into table track_log partition (date="20150828",hour="19");
create table static_PVUV(
date string,
hour string,
pv int,
uv int
)
row format delimited fields terminated by '\t';
insert overwrite table static_PVUV select date,hour,count(url),count(distinct guid)from track_log where date="20150828" group by date,hour;
20150828 18 64972 23938
20150828 19 61162 22330
//在mysql中建立用於接收使用sqoop導出的表格
create table static_PVUV(
date int,
hour int,
pv int,
uv int
);
網盟
http://baike.baidu.com/link?url=3lgUc2Ti-dNlHHT2WpHLBoDPJM7GWzeJW9R564CMSZKJL-F7kn98dsj55JoyQTMizJcX6GMY83KI-M-CmTJQ1aMQ4V2pwgZpPrg4ExQz2k_
深刻分析
1、藉助上個案例建立的表
2、設計一張會話信息表
create table db_track.session_info(
session_id string, //會話id
guid string, //惟一用戶id
trackerU string, //網盟用戶id
landing_url string,
landing_url_ref string,
user_id string,
pv string,
stay_time string,
min_trackTime string,
ip string,
provinceId string
)
partitioned by (date string)
row format delimited fields terminated by "\t" ;
3、生成中間表1
--建立中間表1
create table session_info_tmp1(
session_id string,
guid string,
endUserId string,
pv string,
stay_time string,
min_trackTime string,
ip string,
provinceId string
)
row format delimited fields terminated by "\t" ;
--導入數據
insert overwrite table session_info_tmp1
select
sessionId,
max(guid),
max(endUserId),
count(url),
max(unix_timestamp(trackTime))-min(unix_timestamp(trackTime)),
min(trackTime),
max(ip),
max(provinceId)
from track_log where date='20150828'
group by sessionId ;
4、生成臨時表2
create table session_info_tmp2(
session_id string,
trackTime string,
trackerU string,
landing_url string,
landing_url_ref string
)
row format delimited fields terminated by "\t" ;
--導入數據
insert overwrite table session_info_tmp2
select
sessionId,
trackTime,
trackerU,
url,
referer
from track_log where date='20150828' ;
5、得出會話信息表結果(join)
insert overwrite table session_info partition (date='20150828')
select
a.session_id ,
a.guid ,
b.trackerU ,
b.landing_url ,
b.landing_url_ref,
a.endUserId ,
a.pv ,
a.stay_time ,
a.min_trackTime ,
a.ip ,
a.provinceId
from session_info_tmp1 a join session_info_tmp2 b
on a.session_id=b.session_id and a.min_trackTime=b.trackTime ;
** 求出了每一個session的數據
6、求出需求表結果
日期 UV PV 登陸人數 遊客人數 平均訪問時長 二跳率 獨立IP
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
二跳率
count(case when pv >=2 then guid else null end ) / count(guid)
*****************************************************************
create table visit_users (
date string,
uv string,
pv string,
login_users string,
visit_users string,
stay_time string,
perofsecvis string,
ip string
)
row format delimited fields terminated by "\t" ;
insert overwrite table visit_users select
date date,
count(distinct guid) uv,
sum(pv) pv,
count(case when user_id != '' then user_id else null end) login_users,
count(case when user_id = '' then user_id else null end) visit_users,
avg(stay_time) stay_time,
count(case when pv >=2 then guid else null end ) / count(guid) ,
max(ip) ip
from session_info where date='20150828'
group by date ;
Exec Result:
visit_users.date visit_users.uv visit_users.pv visit_users.login_users visit_users.visit_users visit_users.stay_time visit_users.perofsecvis visit_users.ip
20150828 23928 68036.0 12081 12721 50.10636239012983 0.522538504959277599.244.129.62
Exec Result:
visit_users.date visit_users.uv visit_users.pv visit_users.login_users visit_users.visit_users visit_users.stay_time visit_users.perofsecvis visit_users.ip
20150828 23928 68036.0 12081 12721 50.10636239012983 0.522538504959277599.244.129.62
7、導入mysql表
sqoop --> mysql
select sal,
case when comm is null then 0
else comm end
from emp ;
總結
mysql> create table visit_users(
date varchar(20),
uv int(12),
pv double,
login_users int,
visit_users int,
stay_time double,
perofsecvis double,
ip varchar(20)
);
bin/sqoop export \
--connect jdbc:mysql://localhost.Hdfs-Cdh:3306/db_160729 \
--username root \
--password root123 \
--table visit_users \
--input-fields-terminated-by "\t" \
--export-dir /user/hive/warehouse/db_track.db/visit_users