1.MySQL 引擎是什么,常用的是哪个,知道原理吗
常用的是 InnoDB。大部分情况下选择 InnoDB,除非需要用到某些InnoDB不具备的特性,并且没有其他办法可以替代,否则都应该优先选择 InnoDB 引擎。
-
MyISAM:
-
用途:访问的速度快,以 SELECT、INSERT 为主的应用
-
索引:B tree,FullText,R-tree
-
锁:表锁
-
事务:不支持事务
-
其他:不支持外键。每个 MyISAM 在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为 .MYD (MYData)。索引文件的扩展名是 .MYI (MYIndex)。
-
-
InnoDB:
-
用途:大部分情况下选择 InnoDB,除非需要用到某些 InnoDB不具备的特性,并且没有其他办法可以替代,否则都应该优先选择 InnoDB 引擎。
-
索引:B+ tree,hash(引擎自适应,无法人为干预),FullText(5.6开始)
-
锁:行锁
-
事务:支持
-
其他:对比 MyISAM 的存储引擎,InnoDB 写的处理效率差一些,并且会占用更多的磁盘空间以保存数据和索引。InnoDB 所有的表都保存在同一个数据文件中,InnoDB 表的大小只受限于操作系统文件的大小限制。MyISAM 只缓存索引,不缓存真实数据;InnoDB 不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响。
-
-
MEMORY:
-
用途:存储引擎使用存在于内存中的内容来创建表。主要用于那些内容变化不频繁的代码表或者作为统计操作的中间结果表。
-
索引:hash,B tree
-
锁:表
-
事务:不支持
-
其他:MEMORY 类型的表访问非常的快,因为它的数据是放在内存中的,并且默认使用 HASH 索引,但是一旦服务关闭,表中的数据就会丢失。
-
2.MySQL 优化
-
使用 join 代替子查询。
-
使用索引。
其他还有很多。后面单独写一篇文章。
3.怎么建索引?
# 创建
CREATE [UNIQUE] INDEX [indexName] ON table_name(column)
# 删除
DROP INDEX [indexName] ON mytable
# 查看
SHOW INDEX FROM table_name
扩展:
索引的定义:索引是帮助 MySQL 高效获取数据的数据结构。
优点:
-
提高数据检索的效率,降低数据库的IO成本。
-
通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。
缺点:
-
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
-
实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。
适用的情况:
-
主键自动建立唯一索引;
-
频繁作为查询条件的字段应该创建索引
-
查询中与其它表关联的字段,外键关系建立索引
-
单键/组合索引的选择问题, 组合索引性价比更高
-
查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
-
查询中统计或者分组字段
不适用的情况:
-
表记录太少
-
经常增删改的表或者字段
-
Where 条件里用不到的字段不创建索引
-
过滤性不好的不适合建索引
4.B Tree 和 B+ Tree
-
B-树的关键字、记录和索引是放在一起的;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
-
在B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。
-
在实际应用中B+树的性能要好些。因为B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比B-树多,树高比B-树小,这样带来的好处是减少磁盘访问次数。尽管B+树找到一个记录所需的比较次数要比B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+树的性能可能还会好些,而且B+树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用B+树的缘故。
5.手写 SQL
# user_id login_date
# 1 20200325
# 查询出用户连续三天登录的用户
with t1 as(
select
user_id,
login_date,
row_number() over(parition by user_id order by login_date) rn
from table1
),
t2 as(
select
user_id,
date_sub(login_date,interval rn day) group_date
from t1
)
select user_id
from t1
group by user_id
having count(1)>=3;
6.手写 SQL
# 表A 字段a 值包括 1 2 3 4
# 表B 字段b 值包括 1 1 2 3 5
# 问 a join b 输出的结果
1 1 2 3
# 问 a left join b 输出的结果
1 1 2 3 4
7.Sqoop 增量导入数据怎么实现
通过每日同步脚本:
#! /bin/bash
APP=gmall
sqoop=/opt/module/sqoop/bin/sqoop
if [ -n "$2" ] ;then
do_date=$2
else
do_date=`date -d '-1 day' +%F`
fi
import_data(){
$sqoop import \
--connect jdbc:mysql://hadoop102:3306/$APP \
--username root \
--password 123456 \
--target-dir /origin_data/$APP/db/$1/$do_date \
--delete-target-dir \
--query "$2 and \$CONDITIONS" \
--num-mappers 1 \
--fields-terminated-by '\t' \
--compress \
--compression-codec lzop \
--null-string '\\N' \
--null-non-string '\\N'
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/common/hadoop-lzo-0.4.20.jar com.hadoop.compression.lzo.DistributedLzoIndexer /origin_data/$APP/db/$1/$do_date
}
# 这里才是重点
import_order_detail_activity(){
import_data order_detail_activity "
select
id,
order_id,
order_detail_id,
activity_id,
activity_rule_id,
sku_id,
create_time
from order_detail_activity
where date_format(create_time,'%Y-%m-%d')='$do_date'
"
}
8.Flume 事务实现
输入端 Put 事务:
-
doPut:将批数据先写入临时缓冲区 putList
-
doCommit:检查 channel 内存队列是否足够合并
-
doRollback:channel内存队列空间不足,回滚数据
输出端 Take 事务:
-
doTake:将数据取到临时缓冲区 takeList,并将数据发送到 HDFS
-
doCommit:如果数据全部发送成功,则清除临时缓冲区 takeList
-
doRollback:数据发送过程中如果出现异常,rollback 将临时缓冲区 takeList 中的数据归还给 channel 内存队列
9 Kafka消费者角度考虑是拉取数据还是推送数据
生产者使用 push 模式将消息发布到 Broker,消费者使用 pull 模式从 Broker 订阅消息。因为 push 模式很难适应消费速率不同的消费者。
10. Kafka 中的数据是有序的吗
单分区内有序,多分区的分区与分区间无序。
11.Kafka 数据推送失败怎么处理
后面单独写一篇文章。
12.Kafka 保证生产者精准一次
0.11 版本的Kafka,引入了一项重大特性:幂等性。所谓的幂等性就是指 Producer 不论向 Server 发送多少次重复数据,Server 端都只会持久化一条。幂等性结合 At Least Once 语义,就构成了 Kafka 的 Exactly Once 语义。即:At Least Once + 幂等性 = Exactly Once。
要启用幂等性,只需要将Producer的参数中 enable.idempotence 设置为true即可。Kafka 的幂等性实现其实就是将原来下游需要做的去重放在了数据上游。开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而 Broker 端会对 <PID, Partition, SeqNumber> 做缓存,当具有相同主键的消息提交时,Broker只会持久化一条。
但是 PID 重启就会变化,同时不同的 Partition 也具有不同主键,所以幂等性无法保证跨分区跨会话的 Exactly Once。
13.Kafka 数据重复怎么处理
-
开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而 Broker 端会对 <PID, Partition, SeqNumber> 做缓存,当具有相同主键的消息提交时,Broker只会持久化一条。
-
在下游消费者处理
14.Kafka + Spark Streaming 怎么实现精准一次消费
-
存储层使用事务:手动维护消费消息的偏移量,比如把偏移量存到 MySQL,开启事务。
-
存储层支持幂等性或手动去重:先确保真正处理完数据再提交偏移量。但可能重复消费,所以要做到幂等性,不论消费多少次都不存在重复数据。
15.Kafka 如果 offset 没有发送成功数据会怎样
同步提交offset有失败重试机制。
16.Hive 的优化
-
Map Join:可以用Map Join把小表全部加载到内存在 map 端进行 join,避免 reducer 处理。
-
行列过滤
-
列处理:在 SELECT 中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
-
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
-
-
列式存储
-
采用分区技术
-
合理设置 Map 数:小文件多-减少 Map 数,同一个文件中字段少记录多-增加 Map 数
-
小文件合并:CombineHiveInputFormat
-
合理设置 Reduce 数
-
参数设置:
SET hive.merge.mapfiles = true; -- 默认true,在map-only任务结束时合并小文件
SET hive.merge.mapredfiles = true; -- 默认false,在map-reduce任务结束时合并小文件
SET hive.merge.size.per.task = 268435456; -- 默认256M
SET hive.merge.smallfiles.avgsize = 16777216; -- 当输出文件的平均大小小于16m该值时,启动一个独立的map-reduce任务进行文件merge
-
开启 map 端 combiner(不影响最终业务逻辑):set hive.map.aggr=true;
-
压缩
-
开启 JVM 重用
想要获得更大大厂面试资料,java进阶学习资料,请关注一下公众号