Apache Impala学习

  • Apache Impala
    1. Impala基本介绍

impala是cloudera提供的一款高效率的sql查询工具,提供实时的查询效果,官方测试性能比hive快10到100倍,其sql查询比sparkSQL还要更加快速,号称是当前大数据领域最快的查询sql工具,

impala是参照谷歌的新三篇论文(Caffeine--网络搜索引擎、Pregel--分布式图计算、Dremel--交互式分析工具)当中的Dremel实现而来,其中旧三篇论文分别是(BigTable,GFS,MapReduce)分别对应我们即将学的HBase和已经学过的HDFS以及MapReduce。

impala是基于hive并使用内存进行计算,兼顾数据仓库,具有实时,批处理,多并发等优点。

    1. Impala与Hive关系

impala是基于hive的大数据分析查询引擎,直接使用hive的元数据库metadata,意味着impala元数据都存储在hive的metastore当中,并且impala兼容hive的绝大多数sql语法。所以需要安装impala的话,必须先安装hive,保证hive安装成功,并且还需要启动hive的metastore服务

Hive元数据包含用Hive创建的database、table等元信息。元数据存储在关系型数据库中,如Derby、MySQL等。

客户端连接metastore服务,metastore再去连接MySQL数据库来存取元数据。有了metastore服务,就可以有多个客户端同时连接,而且这些客户端不需要知道MySQL数据库的用户名和密码,只需要连接metastore 服务即可。

Hive适合于长时间的批处理查询分析,而Impala适合于实时交互式SQL查询。可以先使用hive进行数据转换处理,之后使用Impala在Hive处理后的结果数据集上进行快速的数据分析。

    1. Impala与Hive异同

Impala 与Hive都是构建在Hadoop之上的数据查询工具各有不同的侧重适应面,但从客户端使用来看Impala与Hive有很多的共同之处,如数据表元数据、ODBC/JDBC驱动、SQL语法、灵活的文件格式、存储资源池等。

但是Impala跟Hive最大的优化区别在于:没有使用 MapReduce进行并行计算,虽然MapReduce是非常好的并行计算框架,但它更多的面向批处理模式,而不是面向交互式的SQL执行。与 MapReduce相比,Impala把整个查询分成一执行计划树,而不是一连串的MapReduce任务,在分发执行计划后,Impala使用拉式获取数据的方式获取结果,把结果数据组成按执行树流式传递汇集,减少的了把中间结果写入磁盘的步骤,再从磁盘读取数据的开销。Impala使用服务的方式避免每次执行查询都需要启动的开销,即相比Hive没了MapReduce启动时间。

      1. Impala使用的优化技术

使用LLVM产生运行代码,针对特定查询生成特定代码,同时使用Inline的方式减少函数调用的开销,加快执行效率。(C++特性)

充分利用可用的硬件指令(SSE4.2)。

更好的IO调度,Impala知道数据块所在的磁盘位置能够更好的利用多磁盘的优势,同时Impala支持直接数据块读取和本地代码计算checksum。

通过选择合适数据存储格式可以得到最好性能(Impala支持多种存储格式)。

最大使用内存,中间结果不写磁盘,及时通过网络以stream的方式传递。

      1. 执行计划

Hive: 依赖于MapReduce执行框架,执行计划分成 map->shuffle->reduce->map->shuffle->reduce…的模型。如果一个Query会 被编译成多轮MapReduce,则会有更多的写中间结果。由于MapReduce执行框架本身的特点,过多的中间过程会增加整个Query的执行时间。

Impala: 把执行计划表现为一棵完整的执行计划树,可以更自然地分发执行计划到各个Impalad执行查询,而不用像Hive那样把它组合成管道型的 map->reduce模式,以此保证Impala有更好的并发性和避免不必要的中间sort与shuffle。

      1. 数据流

Hive: 采用推的方式,每一个计算节点计算完成后将数据主动推给后续节点。

Impala: 采用拉的方式,后续节点通过getNext主动向前面节点要数据,以此方式数据可以流式的返回给客户端,且只要有1条数据被处理完,就可以立即展现出来,而不用等到全部处理完成,更符合SQL交互式查询使用。

      1. 内存使用

Hive: 在执行过程中如果内存放不下所有数据,则会使用外存,以保证Query能顺序执行完。每一轮MapReduce结束,中间结果也会写入HDFS中,同样由于MapReduce执行架构的特性,shuffle过程也会有写本地磁盘的操作。

Impala: 在遇到内存放不下数据时,版本1.0.1是直接返回错误,而不会利用外存,以后版本应该会进行改进。这使用得Impala目前处理Query会受到一定的限制,最好还是与Hive配合使用。

      1. 调度

Hive: 任务调度依赖于Hadoop的调度策略。

Impala: 调度由自己完成,目前只有一种调度器simple-schedule,它会尽量满足数据的局部性,扫描数据的进程尽量靠近数据本身所在的物理机器。调度器 目前还比较简单,在SimpleScheduler::GetBackend中可以看到,现在还没有考虑负载,网络IO状况等因素进行调度。但目前 Impala已经有对执行过程的性能统计分析,应该以后版本会利用这些统计信息进行调度吧。

      1. 容错

Hive: 依赖于Hadoop的容错能力。

Impala: 在查询过程中,没有容错逻辑,如果在执行过程中发生故障,则直接返回错误(这与Impala的设计有关,因为Impala定位于实时查询,一次查询失败, 再查一次就好了,再查一次的成本很低)。

      1. 适用面

Hive: 复杂的批处理查询任务,数据转换任务。

Impala:实时数据分析,因为不支持UDF,能处理的问题域有一定的限制,与Hive配合使用,对Hive的结果数据集进行实时分析。

    1. Impala架构

Impala主要由Impalad State StoreCatalogd和CLI组成

 

      1. Impalad

Impalad: 与DataNode运行在同一节点上,由Impalad进程表示,它接收客户端的查询请求(接收查询请求的Impalad为Coordinator,Coordinator通过JNI调用java前端解释SQL查询语句,生成查询计划树,再通过调度器把执行计划分发给具有相应数据的其它Impalad进行执行),读写数据,并行执行查询,并把结果通过网络流式的传送回给Coordinator,由Coordinator返回给客户端。同时Impalad也与State Store保持连接,用于确定哪个Impalad是健康和可以接受新的工作。

在Impalad中启动三个ThriftServer: beeswax_server(连接客户端),hs2_server(借用Hive元数据), be_server(Impalad内部使用)和一个ImpalaServer服务。

      1. Impala State Store

Impala State Store: 跟踪集群中的Impalad的健康状态及位置信息,由statestored进程表示,它通过创建多个线程来处理Impalad的注册订阅和与各Impalad保持心跳连接,各Impalad都会缓存一份State Store中的信息,当State Store离线后(Impalad发现State Store处于离线时,会进入recovery模式,反复注册,当State Store重新加入集群后,自动恢复正常,更新缓存数据)因为Impalad有State Store的缓存仍然可以工作,但会因为有些Impalad失效了,而已缓存数据无法更新,导致把执行计划分配给了失效的Impalad,导致查询失败。

      1. CLI

CLI: 提供给用户查询使用的命令行工具(Impala Shell使用python实现),同时Impala还提供了Hue,JDBC, ODBC使用接口。

      1. Catalogd

Catalogd:作为metadata访问网关,从Hive Metastore等外部catalog中获取元数据信息,放到impala自己的catalog结构中。impalad执行ddl命令时通过catalogd由其代为执行,该更新则由statestored广播。

    1. Impala查询处理过程

Impalad分为Java前端与C++处理后端,接受客户端连接的Impalad即作为这次查询的Coordinator,Coordinator通过JNI调用Java前端对用户的查询SQL进行分析生成执行计划树。

Java前端产生的执行计划树以Thrift数据格式返回给C++后端(Coordinator)(执行计划分为多个阶段,每一个阶段叫做一个PlanFragment,每一个PlanFragment在执行时可以由多个Impalad实例并行执行(有些PlanFragment只能由一个Impalad实例执行,如聚合操作),整个执行计划为一执行计划树)。

Coordinator根据执行计划,数据存储信息(Impala通过libhdfs与HDFS进行交互。通过hdfsGetHosts方法获得文件数据块所在节点的位置信息),通过调度器(现在只有simple-scheduler, 使用round-robin算法)Coordinator::Exec对生成的执行计划树分配给相应的后端执行器Impalad执行(查询会使用LLVM进行代码生成,编译,执行),通过调用GetNext()方法获取计算结果。

如果是insert语句,则将计算结果通过libhdfs写回HDFS当所有输入数据被消耗光,执行结束,之后注销此次查询服务。

  • Impala sql语法
    1. 数据库特定语句
      1. 创建数据库

CREATE DATABASE语句用于在Impala中创建新数据库。

CREATE DATABASE IF NOT EXISTS 这里,IF NOT EXISTS是一个可选的子句。如果我们使用此子句,则只有在没有具有相同名称的现有数据库时,才会创建具有给定名称的数据库。

默认就会在hive的数仓路径下创建新的数据库名文件夹。

也可以在创建数据库的时候指定hdfs路径。需要注意该路径的权限。

      1. 删除数据库

Impala的DROP DATABASE语句用于从Impala中删除数据库。 在删除数据库之前,建议从中删除所有表。

    1. 表特定语句
      1. create table语句

CREATE TABLE语句用于在Impala中的所需数据库中创建新表。 需要指定表名字并定义其列和每列的数据类型。

impala支持的数据类型和hive类似,除了sql类型外,还支持java类型。

create table IF NOT EXISTS database_name.table_name (

   column1 data_type,

   column2 data_type,

   column3 data_type,

   ………

   columnN data_type

);

CREATE TABLE IF NOT EXISTS my_db.student(name STRING, age INT, contact INT );

默认建表的数据存储路径跟hive一致。也可以在建表的时候通过location指定具体路径,需要注意hdfs权限问题。

      1. insert语句

Impala的INSERT语句有两个子句: into和overwrite。into用于插入新记录数据,overwrite用于覆盖已有的记录。

insert into table_name (column1, column2, column3,...columnN)

values (value1, value2, value3,...valueN);

Insert into table_name values (value1, value2, value2);

这里,column1,column2,... columnN是要插入数据的表中的列的名称。还可以添加值而不指定列名,但是,需要确保值的顺序与表中的列的顺序相同。

      1. select语句

Impala SELECT语句用于从数据库中的一个或多个表中提取数据。 此查询以表的形式返回数据。

select * from table;

      1. describe语句

Impala中的describe语句用于提供表的描述。 此语句的结果包含有关表的信息,例如列名称及其数据类型。

Describe table_name;

      1. alter table

Impala中的Alter table语句用于对给定表执行更改。使用此语句,我们可以添加,删除或修改现有表中的列,也可以重命名它们。

表重命名:

ALTER TABLE [old_db_name.]old_table_name RENAME TO

 [new_db_name.]new_table_name

向表中添加列

ALTER TABLE name ADD COLUMNS (col_spec[, col_spec ...])

从表中删除列:

ALTER TABLE name DROP [COLUMN] column_name

更改列的名称和类型:

ALTER TABLE name CHANGE column_name new_name new_type

      1. delete、truncate table

Impala drop table语句用于删除Impala中的现有表。此语句还会删除内部表的底层HDFS文件。

注意:使用此命令时必须小心,因为删除表后,表中可用的所有信息也将永远丢失。

DROP table database_name.table_name;

Impala的Truncate Table语句用于从现有表中删除所有记录。保留表结构。

您也可以使用DROP TABLE命令删除一个完整的表,但它会从数据库中删除完整的表结构,如果您希望存储一些数据,您将需要重新创建此表。

truncate table_name;

      1. view视图

视图仅仅是存储在数据库中具有关联名称的Impala查询语言的语句。 它是以预定义的SQL查询形式的表的组合。

视图可以包含表的所有行或选定的行。

Create View IF NOT EXISTS view_name as Select statement

创建视图view

CREATE VIEW IF NOT EXISTS test_view AS select * from table;

查询视图view

select * from test_view

修改视图

ALTER VIEW database_name.view_name为Select语句

删除视图

DROP VIEW database_name.view_name;

      1. order by子句

Impala ORDER BY子句用于根据一个或多个列以升序或降序对数据进行排序。 默认情况下,一些数据库按升序对查询结果进行排序。

select * from table_name ORDER BY col_name

 [ASC|DESC] [NULLS FIRST|NULLS LAST]

可以使用关键字ASC或DESC分别按升序或降序排列表中的数据。

如果我们使用NULLS FIRST,表中的所有空值都排列在顶行; 如果我们使用NULLS LAST,包含空值的行将最后排列。

      1. group by子句

Impala GROUP BY子句与SELECT语句协作使用,以将相同的数据排列到组中。

select data from table_name Group BY col_name;

      1. having子句

Impala中的Having子句允许您指定过滤哪些组结果显示在最终结果中的条件。

一般来说,Having子句与group by子句一起使用; 它将条件放置在由GROUP BY子句创建的组上。

      1. limit

Impala中的limit子句用于将结果集的行数限制为所需的数,即查询的结果集不包含超过指定限制的记录。

select * from table_name limit 10;

      1. with子句

如果查询太复杂,我们可以为复杂部分定义别名,并使用Impala的with子句将它们包含在查询中。

with x as (select 1), y as (select 2) (select * from x union y);

例如:使用with子句显示年龄大于25的员工和客户的记录。

with t1 as (select * from customers where age>25),

   t2 as (select * from employee where age>25)

   (select * from t1 union select * from t2);

      1. distinct

Impala中的distinct运算符用于通过删除重复值来获取唯一值。

select distinct columns… from table_name;

    1. 函数
      1. substr()

字符串截取,从左至右第几个字符开始截取几位

      1. max(),min(),avg()

max求最大值

min求最小值

avg求平均值

      1. dround()

截取数值,四舍五入

      1. truncate()

删除小数点以后得数或N位小数

      1. greatest()

返回表达式列表中最大值

      1. least()

返回表达式列表中最小值

      1. like()

模糊查询

      1. concat(string a,string b…)

多字符串拼接

      1. concat_ws(string sep,string a,string b…)

拼接多个字符串,由指定分隔符分割

      1. length(string a)

字符串长度

      1. trim(string a)

去字符串空格

      1. count(*)

查询记录条数

      1. cast(expr AS type)

将表达式的值转换为任何其他类型
如果表达式值的类型无法转换为目标类型,则结果为Null

将字符类型5转换为int型

      1. typeof(type value)

返回与表达式对应的数据类型的名称

      1. case a when b then c [when d then e]… [else f] end

将表达式与一个或多个可能的值进行比较,并在找到匹配项或未找到时返回相应的结果

      1. case when a then b [when c then d]… [else e] end

测试一系列表达式是否为真,并返回第一个真实表达式的相应结果

      1. coalesce(type v1, type v2, …)

返回第一个不为空的值,如果所有参数都是空值则为空

      1. decode(type expression, type search1, type result1,[type search2, type result2], [type default])

将表达式与一个或多个可能的值进行比较,并在找到或未找到匹配项时返回相应的结果

      1. if(boolean condition, type ifTrue, type ifFalseOrNull)

判断表达式并根据结果是true,false还是返回相应的结果。

      1. ifnull(type a, type ifNull)

判断值是否为空,如果为空则返回对应结构,否则返回原来的值

      1. istrue(boolean)

测试一个布尔表达式真假,真则返回true,假则返回false

      1. isfalse(boolean)

测试一个布尔表达式真假,真则返回false,假则返回true

      1. nullif(expr1,expr2)

如果两个指定的参数是相等的返回空值。如果不相等,则返回expr1的值

      1. nvl(type a, type ifNull)

测试表达式是否空值,如果不是,则返回表达式结果值

      1. uuid()

随机生成UUID

      1. now()

获取当前时间戳

      1. unix_timestamp()

当前时间戳相对于 linux epoch 的秒数,unix_timestamp() , 不带参数, 则返回 '1970-01-01 00:00:00' UTC 到现在的秒数

      1. from_unixtime(int, 'yyyy/MM/dd HH:mm')

将秒数转换到字符串

      1. to_date(timestamp)

将时间戳转换为日期字符串

      1. to_timestamp(bigint unixtime)

将秒数转换成时间戳

      1. to_timestamp(string date, string pattern)

将字符串转换时间戳

      1. trunc(now(), 'YEAR')

select trunc(now(), 'YEAR') --取整到年份, 得到当年 1 月 1 日 0 点 0 分

select trunc(now(), 'MONTH') --取整到月份, 得到当月 1 日 0 点 0 分

select trunc(now(), 'DD') --取整到日期, 得到当天 0 点 0 分

select trunc(now(), 'DAY') --取整到星期, 得到本星期第一天的 0 点 0 分

select trunc(now(), 'HH24') --取整到小时, 得到当前小时的 0 分

select trunc(now(), 'MI') --取整到分钟, 得到当前分钟 0 秒

      1. date_part('year', now())

时间戳提取年

      1. datediff(timestamp enddate, timestamp startdate)

两个时间戳比较

      1. years_add(timestamp t, int n)

时间戳直接相加减

years_sub(timestamp t, int n)

months_add(timestamp t, int n)

months_sub(timestamp t, int n)

days_add(timestamp t, int n)

days_sub(timestamp t, int n)

hours_add(timestamp t, int n)

hours_sub(timestamp t, int n)

minutes_add(timestamp t, int n)

minutes_sub(timestamp t, int n)

  • Impala数据导入方式
    1. load data

首先创建一个表:

create table user(id int ,name string,age int ) row format delimited fields terminated by "\t";

准备数据user.txt并上传到hdfs的 /user/impala路径下去

加载数据

load data inpath '/user/impala/' into table user;

查询加载的数据

select  *  from  user;

    1. insert into values

这种方式非常类似于RDBMS的数据插入方式。

create table t_test2(id int,name string);

insert into table t_test2 values(1,”zhangsan”);

    1. insert into select

插入一张表的数据来自于后面的select查询语句返回的结果。

insert into table table_name select id from test_table;

    1. create as select

建表的字段个数、类型、数据来自于后续的select查询语句。

create table table_name select id from test_table;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值