SparkSQL 运行架构 && hive 的安装实践
TreeNode 体系
Logical Plans 、Expressions 、Physical Operators 都可以使用Tree 表示
– TreeNode 具备一些scala collection 的操作能力和树遍历能力,树的修改是以替换已有节点的方式进行的。
– TreeNode ,内部带一个children: Seq[BaseType] 表示孩子节点,具备foreach 、map 、collect 等针对节点操作的方法,以及transformDown 、transformUp 这样的遍历树上节点,对匹配节点实施变化的方法。
– 三种trait
● UnaryNode 一元节点,即只有一个孩子节
点。Linit 、Filter
● BinaryNode 二元节点,即有左右孩子的二叉节点。Jion 、Union
● LeafNode 叶子节点,没有孩子节点的节点。SetCommand
SqlParser
Sql 解析成Unresolved 逻辑计划(包含UnresolvedRelation 、 UnresolvedFunction 、UnresolvedAttribute )
● 对于命令,会生成一个叶子节点;
● 对于SQL 语句,由lexical 的Scanner来扫描输入,分词,校验,如果符合语法就生成LogicalPlan 语法树,不符合则会提示解析失败。
Analyzer
- 流程是实例化一个SimpleAnalyzer ,定义一些Batch ,然后遍历这些Batch 在RuleExecutor 的环境下,执行Batch 里面的Rules ,每个Rule 会对Unresolved Logical Plan 进行Resolve ,有些可能不能一次解析出,需要多次迭代,直到达到max 迭代次数或者达到fix point 。
- 比较常用的Rules 有ResolveReferences 、ResolveRelations 、StarExpansion 、GlobalAggregates 、typeCoercionRules 和liminateAnalysisOperators 。
- ResolveRelations 、ResolveFunctions 等调用了catalog 这个对象。Catalog 对象里面维护了一个tableName,Logical Plan 的HashMap 结果。通过这个Catalog 目录来寻找当前表的结构,从而从中解析出这个表的字段。
Optimizer
- 将Analyzed Logical Plan 经过对Logical Plan 和Expression 进行Rule 的应用transfrom ,从而达到树的节点进行合并和优化。
- 其中主要的优化的策略总结起来是合并、列裁剪、过滤器下推几大类。对Logical Plan transfrom 的是先序遍历(pre-order) ,而对Expression transfrom的时候是后序遍历(post-order)
val query = sql("select * from (select * from temp_shengli limit 100)a limit 10 ")val query = sql("select 1+2+3+4 from temp_shengli")
整体运行过程
使用时直接调用。。。
RDD操作
package week4
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.SQLContext
case class Person(name: String, age: Int)
object SQLOnSpark {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("SQLOnSpark")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
import sqlContext._
val people: RDD[Person] = sc.textFile("hdfs://hadoop1:8000/dataguru/week4/people.txt")
.map(_.split(",")).map(p => Person(p(0), p(1).trim.toInt))
people.registerAsTable("people")
val teenagers = sqlContext.sql("SELECT name FROM people WHERE age >= 10 and age <= 19")
teenagers.map(t => "Name: " + t(0)).collect().foreach(println)
sc.stop()
}
}
运行结果:Name:Justin
package week4
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.hive.LocalHiveContext
object HiveOnSpark {
case class Record(key: Int, value: String)
def main(args: Array[String]) {
val sparkConf = new SparkConf().setAppName("HiveFromSpark")
val sc = new SparkContext(sparkConf)
val hiveContext = new LocalHiveContext(sc)
import hiveContext._
hql("use saledata")
hql("select c.theyear,count(distinct a.ordernumber),sum(b.amount) from tblStock a join tblStockDetail b on a.ordernumber=b.ordernumber join tbldate c on a.dateid=c.dateid group by c.theyear order by c.theyear")
.collect().foreach(println)
sc.stop()
}
}
package week4
import java.sql.{Connection, DriverManager, ResultSet}
object MySQL_test {
def main(args: Array[String]) {
Class.forName("com.mysql.jdbc.Driver")
val conn = DriverManager.getConnection("jdbc:mysql://hadoop3:3306/test", "hadoop", "hadoop")
try {
val statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE )
val prep=conn.prepareStatement("insert into saledata (theyear,qty,amount) values (\"2003\",2,3)")
prep.executeUpdate()
val rs = statement.executeQuery("select theyear,qty,amount from saledata")
while (rs.next) {
val theyear = rs.getString("theyear")
val qty = rs.getString("qty")
println("theyear = %s, qtyname = %s".format(theyear, qty))
}
} catch {
case e: Exception => e.printStackTrace
}
conn.close
}
}
netstat -nlt 查看TCP端口
总规划:
远程模式搭建hive系统, 也就是采用Mysql作为元数据存储的数据库,并且把mysql安装在hadoop3上面,并且在slave2上面启动metastore service,然后在slave1或者物理机的客户端hadoop上安装hive客户端,然后启动hive来访问slave2的metastore service以访问实际存储在hadoop上的文件。
hive前提,hadoop+yarn启动。
salve上 mysql安装完后,执行如下操作
登录
[root@hadoop9 hadoop]# mysql -uroot -p
//这个不需要
mysql> grant all on *.* to mysql@'%' identified by 'mysql' with grant option;
创建用户名:hadoop,密码:hadoop
mysql> create user 'hadoop' identified by 'hadoop';
mysql> grant all on *.* to hadoop@'%' with grant option;
mysql> quit;
//先退出后,以hadoop的用户名登录,再退出
[root@hadoop9 hadoop]# mysql -u hadoop -p
mysql> create database hive;
mysql> quit;
show databases;
use hive;
show tables;
exit;
ls -lsa
hive的安装:
同样模式,解压后+ 修改配置文件:
hive-site.xml hive-env.sh(需要在conf文件拷贝一份出来)
hive-env.sh:HADOOP_HOME
hive-site.xml :
修改为Jdbc的支持和mysql的驱动程序,以及连接的用户名和密码
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://slave2:3306/hive?=createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hadoop</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>hadoop</value>
<description>password to use against metastore database</description>
</property>
hive.metastore.warehouse.dir
hive的数据是loading,装载的目录,可选择性修改
别忘了拷贝驱动程序到hive/lib目录下
bin/hive 启动hive
show databases;
create tables aaa(aa string.bb int)
这时在缺省目录下 得到/user/hive/warehouse/aaa
show tables;
再打开一个slave2的端口,查看mysql的情况,可以看到现在有了表结构
select * from TBLS
看到有一个表名,即元数据已经放在aaa表里面了。
使用scp命令将slave2拷贝到slave1里。
注意意义,scp -r hive/ hadoop@slave1:…/
这时还无法在slave1中启动,因为还没有配置metasore的配置。
客户端忘记配置Urls,所以客户端slave1直接连接到mysql,而不是连接metasore中
修改slave1中的hive-site.xml:
<property>
<name>hive.metastore.uris</name>
<value>thrift://slave2:9083</value>
<description>Thrift uri for the remote metastore. Used by metastore client to connect to remote metastore.</description>
</property>
作为一个前台服务来启动:
1.先启动slave2的metastore service
hive –service –help查看启动的服务
hive –service metastore(作为一个前台服务来启动的)
2.客户端就可以这样访问元数据,然后对存储在hadoop上的数据进行操作。
在slave1中启动hive,查看表;
3.退出:netstat -nlt 查看端口9083
作为一个后台服务来启动:
1.启动
nohup bin/hive --service metastore > metastore.log 2>&1 &
2.后台退出
.jobs(hive目录下)
kill %num(这里num由启动的【】中num决定)
3.slave1同样可以连接看到slave2中的表
(补充讲解):
metasotre
启动 start-dfs.sh start-yarn.sh
单用户使用hive
bin/hive
多用户使用hive
slave2 : bin/hive –service metastore
slave1 : bin/hive
再增加一个用户
在master(victory)中:使用scp命令将slave2拷贝到slave1里。注意意义,scp -r hive/ hadoop@slave1:…/
master(victory) : bin/hive