大数据面试题专栏点击进入
substring
:用于截取字符串的子串。例如,substring('abcdefg', 2, 4)
返回bcde
,表示从字符串'abcdefg'
的第2个位置开始截取,截取长度为4。concat
:连接多个字符串。例如,concat('hello', 'world')
返回helloworld
,将'hello'
和'world'
连接在一起。concat_ws
:与concat
类似,但可以指定连接字符串之间的分隔符。例如,concat_ws(', ', 'apple', 'banana', 'cherry')
返回apple, banana, cherry
,使用,
作为分隔符连接三个字符串。datediff
:计算两个日期之间的天数差。例如,datediff('2023-10-10', '2023-10-01')
返回9,表示从2023-10-01
到2023-10-10
相差9天。date_add
:在给定日期上增加指定的天数。例如,date_add('2023-10-10', 5)
返回2023-10-15
,在2023-10-10
的基础上增加5天。round
:对数值进行四舍五入。例如,round(3.14159, 2)
返回3.14,将3.14159
保留两位小数四舍五入。floor
:向下取整。例如,floor(3.9)
返回3,取不大于3.9
的最大整数。ceil
:向上取整。例如,ceil(3.1)
返回4,取不小于3.1
的最小整数。cast
:用于类型转换。例如,cast('123' as int)
将字符串'123'
转换为整数123。case when then end
:用于条件判断。例如,select case when age > 18 then '成年' else '未成年' end from users
,根据age
字段的值判断是成年还是未成年。if
:简单的条件判断函数。例如,if(condition, value1, value2)
,如果condition
为真,则返回value1
,否则返回value2
。nvl
:用于处理空值。例如,nvl(column_name, default_value)
,如果column_name
为NULL
,则返回default_value
,否则返回column_name
的值。max
:求最大值。例如,select max(salary) from employees
,返回employees
表中salary
列的最大值。min
:求最小值。avg
:求平均值。count
:计数。sum
:求和。collect_list
:将分组后的某个列值存放在一个数组中,不去重。例如,select collect_list(id) from table
,会将id
列的值收集到一个数组中,每个分组对应一个数组。collect_set
:与collect_list
类似,但会对集合中元素去重。explode
:将数组或映射中的元素拆分成多行。例如,对于一个包含数组字段的表,explode(array_column)
可以将数组中的每个元素作为一行输出。posexplode
:除了将元素拆分成多行,还会返回元素的位置索引。concat
和concat_ws
的区别concat
函数用于简单地连接多个字符串,没有指定分隔符,直接将字符串拼接在一起。concat_ws
函数可以指定一个分隔符,用于在连接字符串时插入分隔符,使得连接后的字符串更具可读性和规范性。例如,在连接多个单词组成一个句子时,concat_ws(' ', 'hello', 'world')
可以清晰地用空格分隔每个单词,而concat('hello', 'world')
则是直接连接成helloworld
,没有分隔。select.. from.. join.. group by.. having.. order by.. limit
from.. join.. group by.. having.. select.. order by.. limit
例如,在执行一个查询时,首先从指定的数据源(from
)读取数据,然后进行表连接(join
)操作,接着按照group by
指定的列进行分组,对分组后的数据应用having
筛选条件,之后进行select
列的选择和计算,最后按照order by
进行排序,并根据limit
限制返回的行数。
where
在分组之前对数据进行筛选,它可以直接使用表中的任意字段进行条件判断,但不能使用聚合函数。having
在分组之后对分组结果进行筛选,只能使用分组字段和聚合函数作为筛选条件,不能使用分组字段以外其他原表字段。假设我们有一个销售数据表,包含字段product_id
(产品ID)、quantity
(销售数量)、date
(销售日期)等。
where
:select * from sales where quantity > 100
。having
:select product_id, sum(quantity) as total_quantity from sales group by product_id having total_quantity > 500
。null
。例如,员工表有一个员工没有部门编号,如果使用左连接,以员工表为主表则该员工会被查询出来,对应的部门表的列为null
。NULL
值。NULL
值,两张表都是主表。假设有两张表,table1
(包含id1
和value1
字段)和table2
(包含id2
和value2
字段),部分数据如下:
table1 | |
---|---|
id1 | value1 |
1 | a |
2 | b |
3 | c |
table2 | |
---|---|
id2 | value2 |
2 | x |
3 | y |
4 | z |
select * from table1 left join table2 on table1.id1 = table2.id2
结果:id1 | value1 | id2 | value2 |
---|---|---|---|
1 | a | null | null |
2 | b | 2 | x |
3 | c | 3 | y |
select * from table1 right join table2 on table1.id1 = table2.id2
结果:id1 | value1 | id2 | value2 |
---|---|---|---|
2 | b | 2 | x |
3 | c | 3 | y |
null | null | 4 | z |
select * from table1 inner join table2 on table1.id1 = table2.id2
结果:id1 | value1 | id2 | value2 |
---|---|---|---|
2 | b | 2 | x |
3 | c | 3 | y |
select * from table1 full outer join table2 on table1.id1 = table2.id2
结果:id1 | value1 | id2 | value2 |
---|---|---|---|
1 | a | null | null |
2 | b | 2 | x |
3 | c | 3 | y |
null | null | 4 | z |
order by
(全局排序)
reduceTask
,即使设置了set mapreduce.job.reduces
大于1也不行。适用于分组聚合的结果数据量已经不大的情况下,可以保证整个数据集的有序性。select * from table order by column_name
,会对table
表中的数据按照column_name
列进行全局排序。sort by
(局部排序)
reduceTask
,每个reduceTask
输出的数据是有序的。它只保证每个分区内的数据有序,不保证全局有序。select * from table sort by column_name
,会在每个分区内对数据按照column_name
列进行排序。distribute by
(自定义分区)
reduceTask
中。通常和sort by
配合使用,distribute by
指定如何分区,sort by
指定分区内数据的排序方式。select * from table distribute by partition_column sort by sort_column
,首先根据partition_column
进行分区,然后在每个分区内按照sort_column
进行排序。order by
对整个数据集进行排序,确保所有数据按照指定列有序,但在大数据集情况下可能导致性能问题,因为只有一个reduceTask
处理所有排序工作,数据量大时可能会内存不足等。sort by
在每个reduceTask
内进行局部排序,适合数据量较大且不需要全局严格有序的场景,能提高处理效率,多个reduceTask
可以并行处理排序任务。distribute by
主要用于将数据按照指定规则分区到不同的reduceTask
,结合sort by
可以实现更灵活的数据分布和局部有序处理。Hive是一个构建在Hadoop上的数据仓库软件,它提供了类似SQL的查询语言,使得用户可以用SQL来查询存放在Hadoop上的数据。Hive是一种结构化数据的存储和查询机制,它可以将SQL语句转换为MapReduce任务在Hadoop上执行。
employees
:CREATE TABLE employees (
id INT,
name STRING,
salary FLOAT
) STORED AS ORC;
当删除这个表时,HDFS中存储该表数据的目录也会被删除。
external
关键字,如create external table 表名
。外部表被删除时,只会删除MySQL中对应的元数据信息,并不会删除HDFS上表中的数据。外部表可以防止误删除实际数据,推荐使用。如果外部表被删除,重写创建表,通过location
指向原本的数据目录可以在创建完表的情况下,直接查询表到中的数据。例如:CREATE EXTERNAL TABLE external_employees (
id INT,
name STRING,
salary FLOAT
) LOCATION '/user/data/external_employees' STORED AS ORC;
删除该外部表时,HDFS上/user/data/external_employees
目录中的数据不会被删除。
where
字句中包含分区条件,则直接从该分区去查找,而不是扫描整个表目录,合理的分区设计可以极大提高查询速度和性能。通常,在管理大规模数据集的时候都需要进行分区,比如将日志文件按天进行分区,从而保证数据细粒度的划分,使得查询性能得到提升。PARTITIONED BY
子句创建分区表。表可以包含一个或多个分区列,如partitioned by (分区列类型,分区列类型..)
。alter table 表名 add partition (分区字段=值)
。例如,为一个日志表log_table
添加一个分区dt=2023-10-10
:alter table log_table add partition (dt='2023-10-10')
。alter table 表名 drop partition(分区字段=值)
,如alter table log_table drop partition (dt='2023-10-10')
。CLUSTERED BY(分区字段) INTO 桶的数量 BUCKETS
。例如:CREATE TABLE bucket_table (
id INT,
data STRING
) CLUSTERED BY (id) INTO 5 BUCKETS STORED AS ORC;
这会将bucket_table
表按照id
列进行哈希分桶,共分为5个桶,数据会根据id
的哈希值分配到不同的桶文件中。桶表可以用于数据抽样、高效连接等操作,例如在连接操作中,如果两个表按照相同的列进行分桶,并且桶的数量成倍数关系,可以提高连接效率。
load data local inpath '文件的路径' overwrite into table 表
:从本地文件系统加载数据到Hive表中,会覆盖表中原有数据。例如,load data local inpath '/home/user/data.txt' overwrite into table my_table;
这里假设data.txt
是本地文件,包含了适合my_table
表结构的数据。执行该命令后,data.txt
中的数据将被加载到my_table
表中,并且如果my_table
表中原来有数据,会被新数据覆盖。load data inpath '文件的路径' overwrite into table 表
:从HDFS文件系统加载数据到Hive表中,也会覆盖表中原有数据。例如,load data inpath '/user/hive/data/hive_data.txt' overwrite into table my_table;
这里假设hive_data.txt
是HDFS上的文件,执行该命令后,hive_data.txt
中的数据将被加载到my_table
表中,同样会覆盖原有的数据。如果文件在HDFS上的路径不存在,可能会导致加载失败,需要确保文件路径的正确性。create table[view] 表 as select 语句 where.. group by;
例如:
create table new_table as select id, name, sum(salary) as total_salary from employees group by id, name;
这会创建一个名为new_table
的新表,并将employees
表中按照id
和name
分组后计算的每个组的总工资插入到新表中。如果使用create view
,则会创建一个视图,而不是实际的表,视图是一个虚拟的表,它基于查询结果定义,可以像表一样进行查询,但不存储实际数据。例如:
create view employee_salary_view as select id, name, salary from employees where department = 'sales';
这里创建了一个名为employee_salary_view
的视图,它显示了sales
部门员工的id
、name
和salary
信息。视图可以方便地对数据进行筛选和展示,而不需要实际创建一个新的表来存储数据,当原始表employees
的数据发生变化时,视图中的数据也会相应更新。
insert into table 表名 select语句...
:将查询结果插入到已存在的表中,如果表中已有数据,会在原有数据基础上追加新数据。
insert into table existing_table select id, name from new_employees;
这里假设existing_table
是已经存在的表,new_employees
是另一个表或查询结果集。执行该语句后,new_employees
表中的id
和name
列的数据将被插入到existing_table
表中,如果existing_table
表原来有数据,新数据会追加到原有数据之后。insert overwrite table 表名 select语句...
:会覆盖表中原有数据,将查询结果插入到表中。
insert overwrite table existing_table select id, name