目录
2、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?
14、mysql 对一个大表做在线ddl,怎么进行实施的才能尽可能降低影响?
一、知识点梳理
(一)数据库定义
1、Data数据:任何描述事物的文字和符号的都可以称为数据。 软件开发就是为了收集数据,从中筛选出有用的信息。
2、Infomation信息:数据经过处理之后得到的内容称为信息。
P.S.数据需要保存,保存的介质有内存和硬盘等。 内存中的数据是临时的,随着系统的关闭,数据也会消失; 硬盘中的数据是永久的,就算系统关闭,数据依然保留。 excel等文件保存数据是一种保存到硬盘中的途径, 但是如果大量数据要保存,文件系统就不再方便。 使用一个系统化的数据仓库才能更高效地处理数据。
3、数据库(DataBase,简称为DB) 运行在操作系统上,按一定的数据结构,保存数据的仓库。是一个电子化的文件柜。 数据永久保存在硬盘中。
4、数据库管理系统(DataBase Manager System,简称为DBMS 通常所说的数据库),是指数据库管理系统,如MySQL、Oracle等。 是一种操作和管理数据库的大型软件,用于建立、使用和维护数据库。
小结:
- 数据Data需要永久保存到数据库中
- 数据库DB是运行在操作系统上的一个软件
- 数据库管理系统DBMS是管理数据库的一个软件
- 学习数据库就是学习如何使用DBMS创建、使用数据仓库来管理数据
(二)数据库的分类
1、关系型数据库
关系型数据库是主流的数据库类型。关系型数据库,数据表直接有关联,能快速地查询出想要的数据。
e.g. SQLServer MySQL Oracle
2、非关系型数据库nosql
数据通过对象的形式保存,对象可以是一个键值对、文档、图片等。
e.g. redis
(三)SQL语句
在关系型数据库中,用于操作数据库的结构化查询语言。
1、查看信息
- 查看所有数据库:show databases;
- 查看所有表:show tables;
- 查看表结构:desc 表名;
- 查看建表语言:show create table 表名;
2、数据库操作
- 创建数据库:create database 数据库名:
- 使用数据库:use 数据库名:
- 删除数据库:drop database 数据库名;
3、数据表操作
- 创建数据表
create table 表名(
字段名 数据类型 [字段特征],
字段名 数据类型 [字段特征],
...
字段名 数据类型 [字段特征]
)
- 删除数据表
drop table 表名;
- 修改数据表
--对表重名
alter table 旧表名 rename to 新表名;
--添加新字段
alter table 表名 add column 字段名 数据类型 字段特征;
--修改字段
alter table 表名 change 旧字段名 新字段名 数据类型 字段特征;
--删除字段
alter table 表名 drop 字段名;
4、添加约束
添加约束的操作通常是对已存在的表进行修改和维护时使用。如果是一张新表,最好在创建表的时候设计好约束。
--添加非空约束
alter table 表名 change 旧字段名 新字段名 数据类型 not null;
--添加主键约束
alter table 表名 add primary key(字段名);
--添加唯一约束
alter table 表名 add unique(字段名);
--添加默认值约束
alter table 表名 alter 字段名 set default '默认值';
--添加外键约束
alter table 从表表名 add foreign key(从表外键字段) references 主表(主表主键字段)
- 建表的同时添加约束
-- 创建数据库gamedb
create database gamedb;
-- 切换数据库
use gamedb;
-- 创建游戏角色表hero
create table hero(
-- 编号 整型 非空 主键 自增
id int not null primary key auto_increment comment '编号',
-- 姓名 字符串 非空 唯一
name varchar(20) not null unique comment '姓名',
-- 定位 字符串 非空
position varchar(20) not null comment '定位',
-- 性别 字符串 非空 默认男
sex char(1) not null default '男' comment '性别',
-- 价格 整型 非空 默认4800
price int not null default '4800' comment '价格',
-- 上架日期
shelf_date date comment '上架日期'
)
-- 创建战斗表battle
create table battle(
hero_id int not null ,
position varchar(20),
-- 外键 hero_id参考hero表中的id字段
foreign key (hero_id) references hero(id)
)
5、数据完整性
数据完整性是指数据精确可靠。不能保存无意义或无效的数据。 如不合理的年龄、全为空的记录、重复记录等。 为了保证保存在数据库中的数据是完整数据,就要在设计数据表时添加一些约束或特征来保证数据完整性。
- 数据类型
整型 | ||
tinyint | 短整型 | 对应java中的byte和short |
int | 整型 | 对应Java中的int |
bigint | 长整型 | 对应Java中的long |
浮点型 | ||
float | 单精度浮点型 | 对应Java中的float |
double | 双精度浮点型 | 对应Java中的double |
decimal(宽度,精度) | 指定保留的小数位数和整体宽度 | 如decimal(4,2) 3.1415926->3.14 |
字符串 | ||
char(长度) | 定长字符串 | char(10)表示占10个字符,就算保存了3个字符,也占10个字符,对 应java中的String |
varchar(长度) | 可变字符串 | varchar(10)表示最多占10个字符,保存了3个字符,就占3个字符, 对应java中的String |
text | 文本 |
日期 | ||
date | 日期 | yyyy-MM-dd |
time | 时间 | HH:mm:ss |
datetime | 日期时间 | yyyy-MM-dd HH:mm:ss |
timestamp(14或8) | 毫秒 | 保存日期的毫秒数.14表示yyyyMMddHHmmss,8表示 yyyyMMdd |
- 完整性约束
完整性约束 | 关键字 | 作用 |
非空约束 | not null | 保证字段值不为空 |
主键约束 | primary key | 保证字段值不重复,用于唯一区分每条记录 |
唯一约束(索引) | unique | 保证字段值不重复 |
默认值约束 | default | 保证字段在没有填充数据时,自动使用默认值填充 |
外键约束 | foreign key references | 保证从表中的数据只能来自于主表 |
6、数据操作
- 增加
insert into 表名 values(值1,值2...)
保证按表中字段顺序添加数据,不能缺少任何一个字段
自增字段用null;默认值字段用default;允许为空字段用null。
insert into 表名(字段1,字段2....) values(值1,值2...)
保证必须写上非空字段,值的顺序和字段 顺序保持一致
- 修改
update 表名 set 字段=值,字段=值 [where 条件]
- 删除
保留自增列的值:
delete from 表名 [where 条件];
重置自增列的值:
truncate table 表名;
如果要删除主从关系且设置了外键的表中的数据,如果从表中有数据,不能直接删除主表中相关数 据,先删除从表中的数据后,才能删除主表中的数据。
- 查询
select [字段|*] from 表名 [where 条件] [order by 字段] [having 条件]
limit N:查询前N条记录 limit N,M:从索引为N的开始查询M条记录
distinct:去重复
order by 字段1,字段2:多字段排序 默认不写是升序asc;降序需要写desc
group by 字段名:根据字段分组
having 统计函数条件
7、常用函数
- 统计函数
sum():求和
avg():平均
count():统计数量
max():最大值
min():最小值
- 字符串函数
concat('值','值',字段,):拼接值或字段
trim():去除首尾空格 ltrim/rtrim:去除首/尾空格
left(length)/right(length):从左/右开始截取指定长度字符串
replace(字符串或字段,旧字符串,新字符串):将字符串中的旧字符串替换为新字符串
substr(字段或字符串,start,length):从start开始截取length个字符
lcase()/ucase:转换小写/大写
instr()/locate():得到字符串2在字符串1中出现的顺序
reverse():翻转字符串
- 数学函数
round()/ceil()/floor():四舍五入取整/向上取整/向下取整
abs():绝对值
pow():次幂
sqrt():开平方
- 时间函数
now()/curdate()curtime():得到当前日期时间
year()/month()/day():得到日期中的指定部分
datediff()/timediff()/timestampdiff():计算时间间隔
- 补充
if(条件,表达式1,表达式2):条件为真,结果为表达式1,条件为假,结果为表达式2 group_concat():拼接分组后的其他字段
8、嵌套查询和多表查询
嵌套查询
select * from 表 where 字段=(select * from 表 where 条件);
select * from 表,(select * from 表)t where 表.字段=t.字段;
多表查询
--交叉连接/笛卡尔积
select * from 表1,表2...;
select * from 表1 cross/inner join 表2;
--内连接
select * from 表1,表2 where 表1.字段=表2.字段;
select * from 表1 cross/inner join 表2 on 表1.字段=表2.字段;
--外连接
--左外连接
select * from 表1 left join 表2 on 表1.字段=表2.字段;-- 保证表1中的数据完整
--右外连接
select * from 表1 right join 表2 on 表1.字段=表2.字段;-- 保证表2中的数据完整
(四)数据库设计
1、实体关系模型:ER图
- 矩形:实体
- 椭圆形:实体的属性
- 菱形:实体之间的关系
实体关系分类
一对一:一个国家有一个领导人
- 根据两个实体创建两张表,都加上主键
- 在其中一张表中添加一个字段,保存另一张表的主键并设置唯一
一对多/多对一:一个班级有多个学生,一个学生不能有多个班级
- 先根据两个实体创建两张表,都加上主键
- 在从表中添加外键字段管理主表中的主键字段
多对多:一个学生学习多门课程,一门课程可以被多个学生学习
- 先根据两个实体创建两张表,都加上主键
- 创建第三张"关系"表,在该表中添加两个字段分别保存两个实体表中的主键
2、范式
数据库设计的规范,简称为范式(NF)。 范式分为第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、BC范式(BCNF)、第四范式(4NF)和第五范式 (5NF)共六种。 这六种范式的级别越高,表示数据库设计的结果越规范,每一个高级版的范式都包含了低级别的范式。
通常设计数据库时,只需满足3NF即可。
第一范式1NF 字段不可再分
第二范式2NF 在满足1NF的基础上,消除部分依赖。 对于联合主键而言,所有非主属性字段必须完全依赖于主属性。
对于联合主键而言,每一个非主属性字段都需要完全依赖于主属性,而不是依赖其中一部分。 在上图中,无法用学号做主键,需要将学号和科目组合为联合主键,通过联合主键才能得到分数。 出学号和科目外,其他字段都是非主键字段,分数完全依赖于联合主键,其他字段不满足,所以进行如下修改。
第三范式3NF 在满足2NF的基础上,消除传递依赖。
(五)JDBC
Java Database Connectivity Java数据库连接 用于Java程序连接不同的数据库。 实际在Java中定义的相关数据库连接时所需的接口,不同的数据库对其进行了实现。
Java提供了一套规范用于连接各种数据库。不同的数据库厂商根据该规范设计连接驱动。
java.sql包下一组接口用于操作数据库。
- Connection接口 用于获取连接对象
- PreparedStatement接口 用于发送sql语句,处理sql语句
- ResultSet接口 用于保存查询后的结果集
1、连接MySQL所需jar文件
- 普通java工程需要手动导入jar文件
- maven项目需要使用依赖自动导入jar文件
2、加载MySQL驱动
//mysql5.5之前版本
Class.forName("com.mysql.jdbc.Driver");
//mysql8之后版本
Class.forName("com.mysql.cj.jdbc.Driver");
3、连接MySQL数据库字符串
String url="jdbc:mysql://localhost:3306/数据库名?serverTimezone=Asia/Shanghai";
String username="root";
String password="root";
查询的步骤
1.获取连接对象Connection
2.构造sql语句String
3.预处理sql语句pst=conn.prepareStatement(sql)
4.给sql语句中的?赋值pst.setXXX(?顺序,值)
5.调用executeQuery()得到ResultSet结果集
6.遍历结果集rs.next()后rs.getXXX(字段顺序/字段名)
7.释放资源
增删改的步骤
1.获取连接对象Connection
2.构造sql语句String
3.预处理sql语句pst=conn.prepareStatement(sql)
4.给sql语句中的?赋值pst.setXXX(?顺序,值)
5.调用executeUpdate()得到受影响的行数
6.释放资源
(六)事务
事务是由一组sql语句组成的执行单元,这些sql之间一般都相互依赖。 这个执行单元要么全部执行,要么全部不执行。
转账 1)select * from 表 where id =1 and money>=1000 2)update 表 set money=money-1000 where id=1 3)update 表 set money=money+1000 where id=2
以上的所有sql组成了一个转账的事务。
1、事务的特性ACID
原子性Atomicity 事务是最小的执行单元
一致性Consistency 事务执行前后,必须让所有数据保持一致状态。(总体数据守恒)
隔离性Isolation 事务并发时相互隔离,互不影响
持久性Durability 事务一旦提交,对数据的改变是永久的
2、事务的使用
提交:commit 回滚:rollback
mysql中事务是默认自动提交的。
查看事务自动提交开启状态:select @@autocommit 1表示开启自动提交 0表示关闭自动提交
设置事务不自动提交:set @@autocommit=0 如果关闭了事务自动提交,在执行某个事务途中,如果出错,可以使用rollback进行回滚,让数据回到事务执行之前的状态。 如果不出错,通过commit提交事务,一旦提交事务,无法进行回滚。
手动提交/回滚事务
- 关闭事务自动提交:set @@autocommit=0
- 开启事务:start transaction;
- 事务要执行的sql;
- 没有提交之前,如果要回滚,使用rollback;
- 如果要提交,使用commit;一旦提交成功,无法rollback。
3、事务并发可能出现的问题
在同一时刻同时执行多个事务时,称为事务并发。 事务并发会有可能出现以下问题
查看事务隔离级别
select @@transatcion_isolation
设置事务隔离级别
set [session|global] transaction isolation level [read uncommitted|read committed|repeatable read|serializable]
(七)视图
视图可以当做数据库中的一个临时表,保存一些较为复杂的查询后的结果, 之后可以直接通过该视图查询数据,不需要再次编写复杂的sql语句。 视图同时可以隐藏一些查询细节,定制查询数据。
-- 查询平均分最高的课程名及其授课教师
-- 创建视图
create view myview as
select s.c_id,avg(cj)avg_cj from score s,course c where s.c_id = c.c_id
group by s.c_id
-- 视图可以当做表使用
select c_name,t_name from teach t2,teacher t1,course c,
(select c_id from myview where avg_cj=(select max(avg_cj) from myview))t
where t1.t_id=t2.t_id and t.c_id=t2.c_id and c.c_id=t2.c_id
-- 删除视图
drop view myview;
(八)触发器
如果要在更新某张表之前或之后,自动执行另一组sql时,可以使用触发器实现。 如表A是客户表,表B是操作日志表,对表A进行更新操作时,将操作的记录保存到表B中。 慎用触发器,因为如果有10000条记录,在修改所有记录时,触发器就会执行10000次,会花费很多时间。
1、创建触发器
create trigger 触发器名
触发时机 触发操作 on 表名 for each row
begin
触发时执行的sql;
end
-- 创建操作日志表
create table log(
log_id int not null primary key auto_increment,
log_opt varchar(20) not null,
log_time datetime not null
)
-- 创建触发器,在向客户表中添加记录后,自动向日志表中添加记录
create trigger mytrigger
after insert on customer for each row
begin
insert into log values(null,'添加了数据',now())
end
2、使用触发器
一旦创建成功触发器,无需刻意调用,在执行相应的操作时,自动执行触发器
-- 只对customer表做插入操作,会自动向log表中添加记录
insert into customer values(null,'测试插入','123123',0,null);
3、删除触发器
drop trigger 触发器名;
(九)存储过程
类似于java中的方法,定义一组用于完成特定功能的sql语句。 定义存储过程后,通过调用存储过程名,就可以执行定义时的内容。 存储过程可以有参数。
1、调用存储过程
-- 调用无参数的存储过程
call 存储过程名();
-- 调用输入型参数的存储过程
call 存储过程名('实参');
-- 调用输出型参数的存储过程
call 存储过程名(@变量);
-- 调用输入输出型参数的存储过程
set @变量
call 存储过程名(@变量)
2、定义存储过程
create procedure 存储过程名([参数类型 参数名 参数数据类型])-- 参数类型分为输入型/输出型/输
入输出型
begin
sql语句;
end
无参数
create procedure 存储过程名()
begin
sql语句
end
-- 创建存储过程,查询每本图书的书名、作者、类型
CREATE PROCEDURE myproc1 () BEGIN
SELECT
book_name,
book_author,
type_name
FROM
book_info bi,
book_type bt
WHERE
bi.type_id = bt.type_id;
END
-- 调用存储过程
call myproc1();
输入型参数
create procedure 存储过程名(in 形参名 数据类型)
begin
sql语句;
end
-- 根据图书类型查询该类型下的所有图书
CREATE PROCEDURE myproc2 (IN lx VARCHAR ( 20 ))
BEGIN
SELECT
*
FROM
book_info bi,
book_type bt
WHERE
bi.type_id = bt.type_id
AND type_name = lx;
END
-- 调用
call myproc2('杂志')
输出型参数
类似于java中有返回值的方法
create procedure 存储过程名(out 形参名 数据类型)
begin
sql语句;
-- 通常需要将查询出的结果通过into赋值给形参
end
-- 根据作者查询图书数量
CREATE PROCEDURE myproc3 ( IN zz VARCHAR (20), OUT book_count INT )
BEGIN
-- 将查询的结果into到参数book_count中
SELECT
count( book_id ) INTO book_count
FROM
book_info
WHERE
book_author = zz;
END
-- 调用存储过程,@x表示将存储过程的输出型参数保存到变量x中
call myproc3('金庸',@x)
-- 查询参数中保存的数据
select @x
输入输出型参数
create procedure 存储过程名(inout 形参名 数据类型)
begin
sql语句;
end
- 查询书名中带有指定文字的图书名、作者和类型
create procedure myproc4(inout keyword varchar(20))
begin
SELECT
book_name,
book_author,
type_name
FROM
book_info bi,
book_type bt
WHERE
bi.type_id = bt.type_id
AND book_name LIKE concat('%',keyword,'%');
end
-- 调用存储过程
set @keyword='龙';
call myproc4(@keyword);
select @keyword;
3、删除存储过程
drop procedure 存储过程名;
4、存储引擎
MySQL5.5版本之前,默认使用MyIsam存储引擎,不支持事务
MySQL5.5版本之后,默认使用InnoDB存储引擎,支持事务
二、数据库企业面试题
1 、数据库的三范式是什么?
第一范式1NF 字段不可再分
第二范式2NF 在满足1NF的基础上,消除部分依赖。 对于联合主键而言,所有非主属性字段必须完全依赖于主属性。
第三范式3NF 在满足2NF的基础上,消除传递依赖。
2、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?
答:8
3、如何获取当前数据库版本?
在cmd里面输入 mysql -V 来获取mysql版本号
4、char 和 varchar 的区别是什么?
不可动和可动。如果是char(10),varchar(10),那么前者必占10字节,后者根据输入内容可以只占其中一小部分字节。
5、MySQL 的内连接、左连接、右连接有什么区别?
数据库中的左连接和右连接的区别可以概括为一句话来表示即左连接where只影响右表,右连接where只影响到左表。而内连接又区别于作为外连接的左右连接。
内连接:结合两张表的记录,返回相关的查询结果,返回的是两个表的交集部分。
左连接:左连接查询,左表的信息全部展示出来,右表只会展示符合搜索条件的信息,不足的地方记为NULL。
右连接:右连接查询,右表的信息全部展示出来,左表只会展示符合搜索条件的信息,不足的地方记为NULL。
6、MySQL 索引是怎么实现的?
索引是帮助MySQL高效获取数据的数据结构。
索引能提高数据查询的效率。
索引:排好序快速查找数据结构!索引会影响where后面的查找,和order by 后面的排序。
7、怎么验证 MySQL 的索引是否满足需求?
需要根据查询需求来决定配置索引的类型,一旦确定索引类型之后,可以使用 explain 查看 SQL 执行计划,确认索引是否满足需求。
8、说一下数据库的事务隔离?
脏读 事务A读取到了事务B未提交的数据
不可 重复 读 事务A中如果要读取两次数据,在这期间,事务B对数据进行了修改并提交,导致事务A读 取两次的情况不一致
幻读 事务A读取id为1~10之间的数据,假如只有id为2和5的数据,在读取期间,事务B添加了 一条id为3的数据,导致事务A多读到了事务B中的数据
9、说一下 MySQL 常用的引擎?
MySQL5.5版本之前,默认使用MyIsam存储引擎,不支持事务。
MySQL5.5版本之后,默认使用InnoDB存储引擎,支持事务。
10、 说一下 MySQL 的行锁和表锁?
行锁:偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度小,发送锁冲突的概率最低,并发度也最高。
表锁:偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发送锁冲突的概率最高,并发度最低。
11、说一下乐观锁和悲观锁?
乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将 比较-设置 这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。
悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,然后再操作资源。
12、MySQL 问题排查都有哪些手段?
- 可以使用 show processlist 命令查看当前所有连接信息。
- 使用 explain 命令查询 SQL 语句执行计划。
- 开启慢查询日志,查看慢查询的 SQL。
13、 如何做 MySQL 的性能优化?
- 选择合适的存储引擎: InnoDB;
- 保证从内存中读取数据;
- 定期优化重建数据库;
14、mysql 对一个大表做在线ddl,怎么进行实施的才能尽可能降低影响?
可以采用中间表。假设你原始表名是“test”,那么步骤如下
建立一个和“test”一样表结构的新表,表名为test_new。create table test_new like test;
将test表中数据拷贝到test_new中。insert into test_new select * from test;
在test_new上执行ddl操作
最后将执行过ddl更新的test_new表改名为test,原test表改名为test_old。Rename table test to test_old, test_new to test;
确认检查无误后drop掉test_old表
如果test表很大,在第二步会消耗很长时间,那么第二步可以以主键ID为准,采用分段导入,一次导入比如5000条数据,多次导入,这样不会对生产环境造成太大影响,假设test表上有自增主键“form_id",那么上面第二步命令变为:
insert into test_new select * from test where form_id between '1' and '5000';
insert into test_new select * from test where form_id between '5001' and '10000';
15、 Redis 是什么?都有哪些使用场景?
Redis定义:
REmote DIctionary Server(远程字典服务器)是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,也被人们称为数据结构服务器。
应用场景:
- 内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
- 取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面
- 模拟类似于HttpSession这种需要设定过期时间的功能
- 发布、订阅消息系统
- 定时器、计数器
16、 Redis 有哪些功能?
- 哨兵(sentinel)和复制(replication)
- 事务
- LUA脚本
- 持久化
- 集群(cluster)
17、Redis 支持的数据类型有哪些?
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sortedset:有序集合)。
18、 怎么保证缓存和数据库数据的一致性?
19、 Redis 如何做内存优化?
- 关闭 Redis 的虚拟内存[VM]功能,即 redis.conf 中 vm-enabled = no
- 设置 redis.conf 中 maxmemory ,用于告知 Redis 当使用了多少物理内存后拒绝继续写入的请求,可防止 Redis 性能降低甚至崩溃
- 可为指定的数据类型设置内存使用规则,从而提高对应数据类型的内存使用效率
- Hash 在 redis.conf 中有以下两个属性,任意一个超出设定值,则会使用 HashMap 存值
- hash-max-zipmap-entires 64 表示当 value 中的 map 数量在 64 个以下时,实际使用 zipmap 存储值
- hash-max-zipmap-value 512 表示当 value 中的 map 每个成员值长度小于 512 字节时,实际使用 zipmap 存储值
- List 在 redis.conf 中也有以下两个属性
- list-max-ziplist-entires 64
- list-max-ziplist-value 512
- 在 Redis 的源代码中有一行宏定义 REDIS-SHARED-INTEGERS = 10000 ,修改该值可以改变 Redis 存储数值类型的内存开销
20、Redis 常见的性能问题有哪些?该如何解决?
- master写内存快照,seve命令调度rdbsave函数,会阻塞主线程的工程,当快照比较大的时候对性能的影响是非常大的,会间断性暂停服务 。所以master最好不要写内存快照。
- master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响master重启时的恢复速度。master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个slave开启AOF备份数据,策略每秒为同步一次。
- master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂的服务暂停现象。
- redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,slave和master最好在同一个局域网内。