You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
322 lines
6.6 KiB
Markdown
322 lines
6.6 KiB
Markdown
7 months ago
|
# 数据库优化
|
||
|
|
||
|
## 优化方向
|
||
|
|
||
|
+ 数据库表设计
|
||
|
+ 索引
|
||
|
+ 分表技术
|
||
|
+ 读写分离
|
||
|
+ 存储过程
|
||
|
+ 配置优化
|
||
|
+ 硬件升级
|
||
|
+ 定时整理
|
||
|
|
||
|
## 数据库表设计
|
||
|
|
||
|
+ 三范式
|
||
|
+ 反三范式
|
||
|
|
||
|
## 运行状态查询
|
||
|
|
||
|
+ 运行状态:为了确认数据库各种操作更适合那种引擎
|
||
|
|
||
|
```sql
|
||
|
show status\G
|
||
|
|
||
|
show [session|global] like '<param>'
|
||
|
|
||
|
-- 查看启动时间 s
|
||
|
show status like 'uptime';
|
||
|
|
||
|
-- 执行过多少次查询
|
||
|
show global status like 'com_select';
|
||
|
|
||
|
-- 执行过多少次删除
|
||
|
show status like 'com_delete';
|
||
|
|
||
|
-- 执行过多少次更新
|
||
|
show status like 'com_update';
|
||
|
|
||
|
-- 查询连接数
|
||
|
show status like 'connections';
|
||
|
|
||
|
-- 显示慢查询
|
||
|
show status like 'slow_queries';
|
||
|
```
|
||
|
|
||
|
## 定位慢查询
|
||
|
|
||
|
+ 配置数据库 my.ini 文件
|
||
|
|
||
|
```ini
|
||
|
[mysqld]
|
||
|
slow-query-log=ON
|
||
|
long_query_time=2
|
||
|
```
|
||
|
|
||
|
+ 定位慢查询
|
||
|
|
||
|
```sql
|
||
|
-- 查看变量
|
||
|
show variables\G
|
||
|
|
||
|
-- 查看慢查询配置 默认 10s
|
||
|
show variables like 'long_query_time';
|
||
|
|
||
|
-- 修改慢查询配置
|
||
|
set long_query_time=1;
|
||
|
|
||
|
-- 显示慢查询
|
||
|
show status like 'slow_queries';
|
||
|
```
|
||
|
|
||
|
+ 测试 构建大表 数据尽量随机
|
||
|
|
||
|
```sql
|
||
|
-- 创建数据库
|
||
|
create database if not exists mytest charset utf8;
|
||
|
|
||
|
-- 使用数据库
|
||
|
use mytest;
|
||
|
|
||
|
-- 创建部门表
|
||
|
create table if not exists dept (
|
||
|
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
|
||
|
dname VARCHAR(20) NOT NULL DEFAULT '',
|
||
|
loc VARCHAR(13) NOT NULL DEFAULT ''
|
||
|
) DEFAULT CHARSET=UTF8;
|
||
|
|
||
|
-- 创建员工表
|
||
|
create table if not exists emp (
|
||
|
empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
|
||
|
ename VARCHAR(20) NOT NULL DEFAULT '',
|
||
|
job VARCHAR(9) NOT NULL DEFAULT '',
|
||
|
mgr VARCHAR(9) NOT NULL DEFAULT '',
|
||
|
hiredate DATE NOT NULL,
|
||
|
sal DECIMAL(7, 2) NOT NULL,
|
||
|
com DECIMAL(7, 2) NOT NULL,
|
||
|
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0
|
||
|
) DEFAULT CHARSET=UTF8;
|
||
|
|
||
|
-- 创建工资级别表
|
||
|
create table if not exists salgrade (
|
||
|
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
|
||
|
losal DECIMAL(17, 2) NOT NULL,
|
||
|
hisal DECIMAL(17, 2) NOT NULL
|
||
|
) DEFAULT CHARSET=UTF8;
|
||
|
|
||
|
-- 测试数据
|
||
|
-- 工资级别
|
||
|
insert into salgrade values (1, 700, 1200);
|
||
|
insert into salgrade values (2, 1201, 1400);
|
||
|
insert into salgrade values (3, 1401, 2000);
|
||
|
insert into salgrade values (4, 2001, 3000);
|
||
|
insert into salgrade values (5, 3001, 9999);
|
||
|
|
||
|
-- 创建存过
|
||
|
-- 定义结束符
|
||
|
set global log_bin_trust_function_creators=TRUE;
|
||
|
|
||
|
delimiter $$
|
||
|
|
||
|
-- 删除自定义函数 rand_string
|
||
|
drop function if exists rand_string $$
|
||
|
create function rand_string(n INT) returns varchar(255)
|
||
|
begin
|
||
|
declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||
|
declare return_str varchar(255) default '';
|
||
|
declare i int default 0;
|
||
|
while i < n do
|
||
|
set return_str = concat(return_str, substring(chars_str, floor(1 + rand()*52), 1));
|
||
|
set i = i + 1;
|
||
|
end while;
|
||
|
return return_str;
|
||
|
end $$
|
||
|
|
||
|
-- 创建自定义函数 rand_num
|
||
|
drop function if exists rand_num $$
|
||
|
create function rand_num() returns int(5)
|
||
|
begin
|
||
|
declare i int default 0;
|
||
|
set i = floor(1 + rand()*500);
|
||
|
return i;
|
||
|
end $$
|
||
|
|
||
|
-- 创建自定义存过 insert_emp
|
||
|
drop procedure if exists insert_emp $$
|
||
|
create procedure insert_emp(in start int(10), in max_num int(10))
|
||
|
begin
|
||
|
declare i int default 0;
|
||
|
set autocommit = 0;
|
||
|
repeat
|
||
|
set i = i + 1;
|
||
|
insert into emp values ((start + i), rand_string(6), 'SALESMAN', 0001, curdate(), 2000, 400, rand_num());
|
||
|
until i = max_num end repeat;
|
||
|
commit;
|
||
|
end $$
|
||
|
|
||
|
-- 创建自定义存过 insert_dept
|
||
|
drop procedure if exists insert_dept $$
|
||
|
create procedure insert_dept(in start int(10), in max_num int(10))
|
||
|
begin
|
||
|
declare i int default 0;
|
||
|
set autocommit = 0;
|
||
|
repeat
|
||
|
set i = i + 1;
|
||
|
insert into dept values ((start + i), rand_string(10), rand_string(8));
|
||
|
until i = max_num end repeat;
|
||
|
commit;
|
||
|
end $$
|
||
|
|
||
|
-- 创建自定义存过 insert_salgrade
|
||
|
drop procedure insert_salgrade $$
|
||
|
create procedure insert_salgrade(in start int(10), in max_num int(10))
|
||
|
begin
|
||
|
declare i int default 0;
|
||
|
set autocommit = 0;
|
||
|
ALTER TABLE emp DISABLE KEYS;
|
||
|
repeat
|
||
|
set i = i + 1;
|
||
|
insert into salgrade values ((start + i), (start + i), (start + i));
|
||
|
until i = max_num end repeat;
|
||
|
commit;
|
||
|
end $$
|
||
|
|
||
|
-- 定义结束符
|
||
|
delimiter ;
|
||
|
|
||
|
-- 测试自定义函数
|
||
|
select rand_string(6);
|
||
|
select rand_num();
|
||
|
|
||
|
call insert_emp(100001, 4000000);
|
||
|
|
||
|
call insert_dept(100, 10);
|
||
|
|
||
|
call insert_salgrade(10000, 1000000);
|
||
|
```
|
||
|
|
||
|
## 执行计划
|
||
|
|
||
|
+ 查看执行计划
|
||
|
|
||
|
```sql
|
||
|
explain SELECT XXX
|
||
|
```
|
||
|
|
||
|
## 索引
|
||
|
|
||
|
索引分类
|
||
|
|
||
|
+ 主键索引
|
||
|
+ 唯一索引
|
||
|
+ 普通索引
|
||
|
+ 全文索引
|
||
|
|
||
|
索引操作
|
||
|
|
||
|
+ 添加索引
|
||
|
|
||
|
```sql
|
||
|
-- 建表语句添加索引
|
||
|
create table test_idx (
|
||
|
-- 主键索引
|
||
|
id int unsigned primary key auto_increment,
|
||
|
-- 唯一索引 内容可以为 NULL
|
||
|
name varchar(32) unique
|
||
|
);
|
||
|
|
||
|
-- 建表后添加主键索引
|
||
|
alter table <table_name> add primary key(<column_name>);
|
||
|
create index <index_name> on <table_name>(<column_name>);
|
||
|
create unique index <index_name> on <table_name>(<column_name>);
|
||
|
|
||
|
create table test_idx1 (
|
||
|
id int unsigned,
|
||
|
name varchar(32)
|
||
|
);
|
||
|
alter table test_idx1 add primary key(id);
|
||
|
create index idx_test_idx1_1 on test_idx1(name);
|
||
|
create unique index uni_name on test_idx1(name);
|
||
|
```
|
||
|
|
||
|
+ 查询索引
|
||
|
|
||
|
```sql
|
||
|
-- 查看表结构
|
||
|
-- 不能显示索引名字
|
||
|
desc <table_name>;
|
||
|
desc test_idx;
|
||
|
|
||
|
-- 查看索引
|
||
|
show indexes from <table_name>\G
|
||
|
show index from <table_name>\G
|
||
|
show keys from <table_name>\G
|
||
|
|
||
|
show indexes from test_idx\G
|
||
|
show index from test_idx\G
|
||
|
show keys from test_idx\G
|
||
|
```
|
||
|
|
||
|
+ 删除索引
|
||
|
|
||
|
```sql
|
||
|
-- 删除普通索引
|
||
|
drop index <index_name> on <table_name>;
|
||
|
alter table <table_name> drop index <index_name>;
|
||
|
|
||
|
drop index uni_name on test_idx1;
|
||
|
alter table test_idx1 drop index uni_name;
|
||
|
|
||
|
--删除主键索引
|
||
|
alter table <table_name> drop primary key;
|
||
|
|
||
|
alter table test_idx1 drop primary key;
|
||
|
```
|
||
|
|
||
|
+ 修改索引
|
||
|
|
||
|
```sql
|
||
|
-- 先删除再重建
|
||
|
drop index <index_name> on <table_name>;
|
||
|
create index uni_name on test_idx1(name);
|
||
|
```
|
||
|
|
||
|
+ 索引使用
|
||
|
|
||
|
```text
|
||
|
1. 作为查询条件
|
||
|
2. 查询较为频繁
|
||
|
3. 字段变化不频繁
|
||
|
4. 字段唯一性比较强
|
||
|
5. 组合索引最左匹配
|
||
|
6. 模糊查询'%xxx'不会使用索引
|
||
|
7. or 条件的所有查询条件都要有索引
|
||
|
8. 类型严格匹配才会使用索引
|
||
|
```
|
||
|
|
||
|
+ 查看索引使用情况
|
||
|
|
||
|
```sql
|
||
|
|
||
|
show status like 'handler_read%'
|
||
|
-- 值越高 使用索引越高
|
||
|
show status like 'handler_read_key%'
|
||
|
show status like 'handler_read_rnd_next%'
|
||
|
```
|
||
|
|
||
|
+ 数据导入小技巧
|
||
|
|
||
|
```sql-211
|
||
|
-- 导入前禁用索引
|
||
|
alter table <table_name> disable keys;
|
||
|
|
||
|
-- 导入后恢复索引
|
||
|
alter table <table_name> enable keys;
|
||
|
|
||
|
-- innodb
|
||
|
1. 事先按主键排序
|
||
|
2. set unique_checks=0; 关闭唯一检查
|
||
|
3. set autocommit=0; 关闭自动提交
|
||
|
```
|