首页 Mysql笔记
文章
取消

Mysql笔记

mysql

下载安装

下载地址: https://www.mysql.com/downloads/

创建和使用数据库

  • 登录数据库:
    1
    
    mysql -uroot -proot
    
  • 显示数据库 show databases;
  • 创建数据库 create database test;
  • 访问数据库 mysql> use test;
  • 显示表 show tables;
  • 创建表
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    create table `user` (
      `id` int(11) not null auto_increment comment '主键',
      `username` varchar(48) default null comment '用户名',
      `password` varchar(48) default null comment '密码',
      `create_time` timestamp not null default current_timestamp comment '创建时间',
      `update_time` timestamp not null comment '修改时间',
      `state` int not null comment '状态',
      primary key (`id`)
    )engine=innodb default charset=utf8 comment='用户表';
    
  • 查看表结构:describe user;或者desc user;

  • 插入数据
    • 将文本文件加载pet.txt到 pet表中,使用以下语句: load data local infile '/path/user.txt' into table user;
    • 普通脚本插入:
      1
      
      insert into `user` values (1,'tyw','123','','',0);
      
  • 更新数据
    1
    
    update `user` set username = 'tboss' where id = 1;
    
  • 查询数据
    1
    
    select * from `表名`;
    

索引

  • 查看表索引
1
2
3
show index from `表名`;
show keys from `表名`;

  • 创建索引
1
2
3
4
5
6
7
8
-- 普通索引
create index index_username on `表名` (username);
-- 全文索引
create fulltext index index_username on `表名` (username);
-- 主键索引
alter table `表名` add primary key (id);
-- 外键索引
alter table `表名` add unique (id);
  • 删除索引
1
2
3
4
5
6
7
8
drop index index_username on user;

alter table user drop index index_username;
-- 删除主键索引
alter table user drop primary key;
-- 删除外键索引
alter table user drop unique;

索引查询注意

  • like时“%aa%”不会使用索引,而like “aa%”会使用索引
  • where子句中使用了索引的话,order by中的列不会使用索引

字段操作

  • 添加字段:
    1
    
    alter table user add column extend varchar(10) after id;
    
  • 修改字段:
    1
    2
    
    alter table user modify column extend varchar(11) not null comment '字段备注';
    alter table user change column extend extend1 varchar(11) default null comment '字段备注';
    
  • 删除表字段:
    1
    2
    
    alter table 表名 drop column 字段名;
    create table 新表名 select 字段1, 字段2 from 原表名;
    

数据操纵语句(DML)

  • 指定名称插入:insert into user (name,credate,sal,deptno) values ('zhangsan','2018-01-01','2000',1)
  • 不指定名称插入:insert into user values ('zhangsan','2018-01-01','2000',1)
  • 批量插入数据:insert into user values(1,'dept1'),(2,'dept2')
  • 修改记录:update user set sal='4000',deptno=2 where ename='zhangsan'
  • 删除记录:delete from user where ename='zhangsan'

查询

  • 查询所有记录:select * from user
  • 查询不重复的记录:select distinct deptno from user
  • 条件查询:select * from user where deptno=1 and sal<3000
  • 排序和限制:select * from user order by deptno desc limit 2
  • 分页查询(查询从第0条记录开始10条):select * from user order by deptno desc limit 0,10
  • 聚合(查询部门人数大于1的部门编号):select deptno,count(1) from user group by deptno having count(1) > 1
  • 连接查询:select * from user e left join user2 d on e.deptno=d.deptno
  • 子查询:select * from user where deptno in (select deptno from user2)
  • 记录联合:select deptno from user union select deptno from user2

数据控制语句(DCL)

权限相关

  • 授予操作权限(将test数据库中所有表的select和insert权限授予test用户):grant select,insert on test.* to 'test'@'localhost' identified by '123'
  • 查看账号权限:show grants for 'test'@'localhost'
  • 收回操作权限:revoke insert on test.* from 'test'@'localhost'
  • 授予所有数据库的所有权限:grant all privileges on *.* to 'test'@'localhost'
  • 授予所有数据库的所有权限(包括grant):grant all privileges on *.* to 'test'@'localhost' with grant option
  • 授予SUPER PROCESS FILE权限(系统权限不能指定数据库):grant super,process,file on *.* to 'test'@'localhost'
  • 只授予登录权限:grant usage on *.* to 'test'@'localhost'

帐号相关

  • 删除账号:drop user 'test'@'localhost'
  • 修改自己的密码:set password = password('123')
  • 管理员修改他人密码:set password for 'test'@'localhost' = password('123')

其他

字符集相关

  • 查看字符集:show variables like 'character%'
  • 创建数据库时指定字符集:create database test2 character set utf8

时区相关

  • 查看当前时区(UTC为世界统一时间,中国为UTC+8):show variables like "%time_zone%"
  • 修改mysql全局时区为北京时间,即我们所在的东8区:set global time_zone = '+8:00';
  • 修改当前会话时区:set time_zone = '+8:00'
  • 立即生效:flush privileges

连接数(默认151 最大可以达到16384 设置在80% 13000左右比较合适)

MySQL: ERROR 1040: Too many connections 设置较大的 max_connections 值时,可能会导致数据库因接受了太多的连接而性能下降,甚至因为资源耗尽而无法响应的风险

查看最大连接数设置

1
show variables like '%max_connections%';

查看当前实际最大使用连接数

1
show global status like 'Max_used_connections';

设置最大连接数

1
2
3
4
# 立即生效,重启后失效
set GLOBAL max_connections=1000;
# 修改mysql安装目录配置文件my.ini,“max_connections”的值,默认最大连接数是100重启后生效

查看当前进程

1
show processlist;

优化

  • 表关联查询时务必遵循 小表驱动大表 原则;
  • 使用查询语句 where 条件时,不允许出现 函数,否则索引会失效;
  • 使用单表查询时,相同字段尽量不要用 OR,因为可能导致索引失效,比如:SELECT * FROM table WHERE name = ‘zhangsan’ OR name = ‘lisi’,可以使用 UNION 替代;
  • LIKE 语句不允许使用 % 开头,否则索引会失效;
  • 组合索引一定要遵循 从左到右 原则,否则索引会失效;比如:SELECT * FROM table WHERE name = ‘张三’ AND age = 18,那么该组合索引必须是 name,age 形式;
  • 索引不宜过多,根据实际情况决定,尽量不要超过 10 个;
  • 每张表都必须有 主键,达到加快查询效率的目的;
  • 分表,可根据业务字段尾数中的个位或十位或百位(以此类推)做表名达到分表的目的;
  • 分库,可根据业务字段尾数中的个位或十位或百位(以此类推)做库名达到分库的目的;
  • 表分区,类似于硬盘分区,可以将某个时间段的数据放在分区里,加快查询速度,可以配合 分表 + 表分区 结合使用;

删除冗余和重复索引

1
2
3
4
5
//反例
KEY `idx_userId` (`userId`)
KEY `idx_userId_age` (`userId`,`age`)
//正例,删除userId索引,因为组合索引(A,B)相当于创建了(A)和(A,B)索引
 KEY `idx_userId_age` (`userId`,`age`)

索引不宜太多,一般5个以内

where子句中考虑使用默认值代替null

1
2
3
4
//反例
select * from user where age is not null;
//正例,设置0为默认值
select * from user where age>0;

避免在where子句中使用or来连接条件

1
2
3
4
5
6
7
8
//使用union all
select * from user where userid=1
unionall
select * from use rwhere age = 18

//或者分开两条sql写:
select * from user where userid=1
select * from user where age = 18

优化like语句

%放关键字后面

1
select userId,namefrom user where userId like'123%';

避免死锁

  1. 理的设计索引,区分度高的列放到组合索引前面,使业务 SQL 尽可能通过索引定位更少的行,减少锁竞争。
  2. 调整业务逻辑 SQL 执行顺序, 避免 update/delete 长时间持有锁的 SQL 在事务前面。
  3. 避免大事务,尽量将大事务拆成多个小事务来处理,小事务发生锁冲突的几率也更小。
  4. 以固定的顺序访问表和行。比如两个更新数据的事务,事务 A 更新数据的顺序为 1,2;事务 B 更新数据的顺序为2,1。这样更可能会造成死锁。
  5. 在并发比较高的系统中,不要显式加锁,特别是是在事务里显式加锁。如 select … for update 语句,如果是在事务里(运行了 start transaction 或设置了autocommit 等于0),那么就会锁定所查找到的记录。
  6. 尽量按主键/索引去查找记录,范围查找增加了锁冲突的可能性,也不要利用数据库做一些额外额度计算工作。比如有的程序会用到 “select … where … order by rand();”这样的语句,由于类似这样的语句用不到索引,因此将导致整个表的数据都被锁住。
  7. 优化 SQL 和表设计,减少同时占用太多资源的情况。比如说,减少连接的表,将复杂 SQL 分解为多个简单的 SQL。

::: danger 警告 在使用 MySQL 或 MariaDB,不要用“utf8”编码,改用“utf8mb4”。这里(https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4)提供了一个指南用于将现有数据库的字符编码从“utf8”转成“utf8mb4”。 MySQL 的“utf8mb4”是真正的“UTF-8”。 MySQL 的“utf8”是一种“专属的编码”,它能够编码的 Unicode 字符并不多。 :::

缓存清理

查看是否生效

1
select @@query_cache_type;

1.在 query_cache_type 打开的情况下,如果你不想使用缓存,需要指明 select sql_no_cache id,name from tableName; 2.当sql中用到mysql函数,也不会缓存

查看缓存的状态

1
show status like '%Qcache%';
名称 备注
Qcache_free_blocks 目前还处于空闲状态的 Query Cache 中内存 Block 数目
Qcache_free_memory 目前还处于空闲状态的 Query Cache 内存总量
Qcache_hits Query Cache 命中次数
Qcache_inserts 向 Query Cache 中插入新的 Query Cache 的次数,也就是没有命中的次数
Qcache_lowmem_prunes 当 Query Cache 内存容量不够,需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数
Qcache_not_cached 没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL
Qcache_queries_in_cache 目前在 Query Cache 中的 SQL 数量
Qcache_total_blocks Query Cache 中总的 Block 数量

禁用/开启查询缓存

1
2
set session query_cache_type=off;
set session query_cache_type=on;

缓存清理

1
2
3
FLUSH QUERY CACHE; -- 清理查询缓存内存碎片。
RESET QUERY CACHE; -- 从查询缓存中移出所有查询。
FLUSH TABLES; -- 关闭所有打开的表,同时该操作将会清空查询缓存中的内容。

参考资料

本文由作者按照 CC BY 4.0 进行授权

MongoDB笔记

Redis笔记

载入天数...载入时分秒...