数据库调优
调优目标
如何定位需要调优的问题
调优的维度和步骤
具体的调优层面
优化mysql的服务器
优化数据结构
- 调优目标
-
尽可能的节省系统的资源,内存,cpu,可以让系统提供更大载荷发的服务。就是吞吐量调到最大。
-
对数据库的结构和参数调整,提高用户操作的响应速度。
-
减少系统的瓶颈,提高mysql整体性能。
总结:加大吞吐量,提高响应速度,减少系统瓶颈。
- 如何定位需要调优的问题
-
用户反馈
-
日志分析(mysql日志分析)
-
服务器资源监控系统来进行监控
-
数据库内部状态监控
-
其他比如对锁,事物等等进行监控
- 调优的维度和步骤
首先要明确:正常来说调优的对象是数据库系统(DBS),对开发人员来说,维护好DBMS就可以了
维护DBMS 数据库管理系统,就不能单纯的从sql语句上面来优化,还包括数据库的部署配置,架构设计等等。
步骤:
数据库选型 mysql oracle sqlServer redis
通过业务场景:对事务的要求比较高,安全性较高就可以选择商用数据库oracle sqlserver
oracle单表存储上亿条数据,都是没有问题的,如果设计的合理,都不用分库分表
开源的mysql,可以选择存储引擎,对事务有要求innodb,对事务没有要求 myisam 这个更快
搜索类的系统,缓存型数据库 redis es mysql+redis+es是和可以组合
优化库的架构 主从复制 表的结构
库的优化
主从复制
读写分离
读一台数据库
写一台数据库
读写数据库通过技术手段mycat进行同步
数据分片(针对500万以上级别数据,进行分片)电商 互联网高并发的应用
把数据分库分表
分库 不讲
分表:
冷热数据分离 就可以减少表的宽度 mysql最多4096列
每一行的数据大小是不能超过65535字节的
热数据(字段操作比较频繁的)
冷数据(字段操作不平凡)
增加中间表
如果两张表要经常关联查询,而又不能反范式的时候,
可以创建中间表,就是将经常要查询的数据插入到中间表中,
然后将原来的联合查询,改成只查询中间表。
举例:学生信息表,班级表
现在有一个模块需要经常查询 学生姓名,班级名称,班级班长的学生信息
就可以创建一个 temp_student 中间表(视图),存储学生姓名,班级名次,班长名字的信息
表的优化:
三大范式+反范式 如果多表关联查询比较多,就尝试反范式 单表查询--在应用层组合
优化逻辑查询
比如索引index的优化(重点是要知道如何使用索引)
使用缓存机制 比如使用缓存数据库redis搭配使用
-- 查看员工中名字以WAR开头的人都有谁?
-- 效率高于第二个
select * from emp e where e.ename like "war%";
-- where子句中用了库函数(里面有逻辑算法)
select * from emp e where substring(ename,1,3) = 'war';
-- 查看 20 号部门和30号部门的员工有哪些?
-- 效率高于第二个
select * from emp e where e.deptno = 20 or e.deptno = 30;
select * from emp e where e.deptno in(20,30);
-- 关联的时候,要小表驱动大表 emp 和dept 用dept作为主表 去驱动emp
-- 插入数据优化
/*
影响插入数据速度的因素:
有索引,唯一性校验,一次性插入的条数
如果有大量的数据可以在新增数据之前先禁用,新增完后再开启
*/
-- 在插入之前可以禁用索引
alter table emp disable keys; -- 禁用
alter table emp enable keys; -- 启用
-- 可以禁用唯一检查
set unique_checks = 0; -- 禁用
set unique_checks = 1; -- 开启
-- 批量插入
insert emp(ename) values("Andy")
insert emp(ename) values("Andy")
insert emp(ename) values("Andy"),("Andy"),("Andy"),("Andy"),("Andy"),("Andy");
-- 禁用外键检查
set foreign_key_checks = 0; -- 禁用
set foreign_key_checks = 1; -- 开启
-- 禁用自动提交(mysql里面默认是开启的)
set autocommit = 0; -- 禁用 一次性的,只要你关闭连接,从新再连,就又会默认开启,如果要长久关闭,就可以去修改改配置文件
set autocommit = 1; -- 开启
show variables like 'autocommit';
-- 插入一条数据,然后关闭连接,从新再连,查看数据是否还存在
insert emp(empno) values(88888);
select * from emp order by empno desc;