MySQL的存储引擎
常用引擎的区别
mysql有三种存储引擎分别为
InnoDB 、MyiSAM、Memory
三种存储引擎的区别
InnoDB | MyiSAM | Memory |
---|---|---|
mysql5.5之后默认的存储引擎 | mysql5.5之前默认的存储引擎 | 内存存储引擎(很少用到) |
支持事务 | 不支持事务 | |
支持外键(是mysql众多存储引擎中唯一支持外键的) | 不支持外键 | |
行级锁(仅对指定行记录进行加锁) | 表级锁(对指定表进行加锁) |
如何选择存储引擎
首选InnoDB
MySQL5.5之后默认的存储引擎
支持事务,支持外键,支持行级锁
保证数据的完整性,一致性
如果对表的操作有插入和查询,还有更新,删除等操作,建议使用InnoDB
数据库的五种分类
DDL(Data Definition Language)数据定义语言
创建
create database 数据库名;
create database 数据库名 charset 字符集;
create table 表名(列名(字段名) 数据类型,…)
create table 新表 like 老表;
查询
show databases;
show create database 数据库名; 查看建库语句
show tables;
show create table 表名;
desc 表名 ;查看表结构;
修改
alter database 数据库名 charset 字符集;
alter table 表名 add 列名 类型;
alter table 表名 modify 列名 新类型;
alter table 表名 change 旧列名 新列名 新类型;
alter table 表名 drop 列名;
alter table 表名 charset 字符集;
rename table 旧表名 to 新表名;
删除
drop database 数据库名;
drop table 表名;
使用数据库
select database();查看当前使用的数据库
use 数据库; 切换(使用)数据库
DML(Data Manipulation Language)数据操作语言
添加记录
insert into 表名 (列名1,列名2…)values(值1,值2…);
insert into 表名 values(值1,值2…);必须与表列顺序一致,查看desc表名
注意:字符串可以插入一切类型,MySQL底层进行了隐式转换
修改记录
update 表名 set 列名1=新值,列名2=新值…[where条件]
删除记录
delete from 表名 [where 条件] 【这里最好要加上条件】
注意:[ ]中的内容可写可不写
DQL(Data Query Language) 数据查询语言
基本查询用法
select * from 表名;
select distinct 列名 from 表名; 去重的关键字distinct
ifnull(列名,默认值)如果该列有值那么就直接返回,如果为null返回默认值
select 列名[as] 列别名 from 表名 [as] 表别名;
高级查询用法
条件查询
select … from 表名 where 条件
关系运算符 > < =…
逻辑运算符 && and , || or ,! not
select … from 表名 where 列名 in(值1,…);
select… from 表名 where 列名 between 较小的值 and 较大的值
select …from 表名 where 列名 is 【not】null
select …from 表名 where 列名 like ‘通配符字符串’
select …from 表名 order by 排序列[asc|desc],排序列[asc|desc]
注意:多字段排序,后面的排序结果是在前面排序的基础之上
聚合函数:count、max、min、sum、avg
select 分组列from 表名 group by 分组列 having 分组后条件过滤
注意:where在分组前进行条件过滤,不能使用聚合函数
having在分组后进行条件过滤,可以使用聚合函数
select …from 表名 limit 开始索引,每页显示个数;
sql执行先后问题
select … from 表名 where 条件 group by 分组 having 分组后条件 order by 排序列[asc|desc] limit 分页;
内连接
- 隐式内连接
select … from 左表,右表 where 连接条件; - 显示内连接
select…from 左表[inner] join 右表 on 连接条件;
外连接
- 左外连接
select …from 左表 left [outer] join 右表 on 连接条件; - 右外连接
select …from 右表 right [ outer] join 左表 on 连接条件;
子查询
注意:
子查询结果为单列,肯定作为条件在where后面使用
select …from 表名 where 字段 in(子查询);
子查询结果为多列,肯定作为虚拟表在from后面使用
select …from (子查询) as 表别名;
查询实际应用
首先添加数据库名,数据库表,基本数据
create database text;
use text;
-- 部门表
CREATE TABLE dept (
id INT PRIMARY KEY auto_increment, -- 部门id
dname VARCHAR(50), -- 部门名称
loc VARCHAR(50) -- 部门位置
);
-- 添加4个部门
INSERT INTO dept(id,dname,loc) VALUES
(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'财务部','深圳');
-- 职务表
CREATE TABLE job (
id INT PRIMARY KEY,
jname VARCHAR(20), -- 职务名称
description VARCHAR(50) -- 职务描述
);
-- 添加4个职务
INSERT INTO job (id, jname, description) VALUES
(1, '董事长', '管理整个公司,接单'),
(2, '经理', '管理部门员工'),
(3, '销售员', '向客人推销产品'),
(4, '文员', '使用办公软件');
-- 员工表
CREATE TABLE emp (
id INT PRIMARY KEY, -- 员工id
ename VARCHAR(50), -- 员工姓名
job_id INT, -- 职务id 外键
mgr INT , -- 上级领导
joindate DATE, -- 入职日期
salary DECIMAL(7,2), -- 工资 99999.99
bonus DECIMAL(7,2), -- 奖金 99999.99
dept_id INT, -- 所在部门编号 外键
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);
-- 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES
(1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
(1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);
-- 工资等级表
CREATE TABLE salarygrade (
grade INT PRIMARY KEY, -- 等级
losalary INT, -- 最低工资
hisalary INT -- 最高工资
);
-- 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);
练习
--简单查询
--查询emp表
select * from emp;
--查询emp表吴用的信息
select * from emp where ename="吴用";
--查询emp表的salary的最大值是谁
--1.子查询
SELECT ename,salary from emp WHERE salary=(SELECT MAX(salary) from emp)
--2.直接查询
SELECT ename,salary FROM emp ORDER BY salary DESC LIMIT 1;
--查询emp中的数据工薪在40000到50000之间的数据
SELECT * FROM emp WHERE salary BETWEEN 40000 AND 50000;
--多表查询
-- 1 查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述
-- 1.1 确定几张表?
SELECT * FROM emp e INNER JOIN job j;
-- 1.2 确定连接条件
SELECT * FROM emp e INNER JOIN job j ON e.job_id = j.id;
-- 1.3 确定显示字段(列)
SELECT e.id,e.ename,e.salary,j.jname,j.description FROM emp e INNER JOIN job j ON e.job_id = j.id;
-- 2 查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
-- 2.1 确定几张表?
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d;
-- 2.2 确定连接条件
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d ON e.job_id = j.id AND e.dept_id = d.id; -- 了解
SELECT -- 推荐
*
FROM
emp e
INNER JOIN job j
ON e.job_id = j.id
INNER JOIN dept d
ON e.dept_id = d.id ;
-- 2.3 确定显示字段
SELECT
e.id,
e.ename,
e.salary,
j.jname,
j.description,
d.dname,
d.loc
FROM
emp e
INNER JOIN job j
ON e.job_id = j.id
INNER JOIN dept d
ON e.dept_id = d.id ;
-- 3 查询所有员工信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
-- 3.1 确定几张表?
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade sg;
-- 3.2 确定连接条件
SELECT
*
FROM
emp e
INNER JOIN job j
ON e.job_id = j.id
INNER JOIN dept d
ON e.dept_id = d.id
INNER JOIN salarygrade sg
ON e.salary BETWEEN sg.losalary
AND sg.hisalary ;
-- 3.3 确定显示字段
SELECT
e.id,
e.ename,
e.salary,
j.jname,
j.description,
d.dname,
d.loc,
sg.grade
FROM
emp e
INNER JOIN job j
ON e.job_id = j.id
INNER JOIN dept d
ON e.dept_id = d.id
INNER JOIN salarygrade sg
ON e.salary BETWEEN sg.losalary
AND sg.hisalary ;
-- 4 查询经理的信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
-- 4.1 确定几张表
SELECT * FROM emp e
INNER JOIN job j
INNER JOIN dept d
INNER JOIN salarygrade;
-- 4.2 确定连接条件
SELECT * FROM emp e
INNER JOIN job j ON e.job_id = j.id
INNER JOIN dept d ON e.dept_id = d.id
INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 4.3 确定显示字段
SELECT e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,sg.grade FROM emp e
INNER JOIN job j ON e.job_id = j.id
INNER JOIN dept d ON e.dept_id = d.id
INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 4.4 确定业务条件
SELECT e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,sg.grade FROM emp e
INNER JOIN job j ON e.job_id = j.id
INNER JOIN dept d ON e.dept_id = d.id
INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary
WHERE j.jname = '经理';
-- 5 查询出所有部门编号、部门名称、部门位置、部门人数
-- 5.1 查询出部门人数 分组+聚合
SELECT dept_id,COUNT(*) AS total FROM emp GROUP BY dept_id;
-- 5.2 查询的结果作为虚拟表与部门表建立关联
SELECT d.id,d.dname,d.loc,e.total FROM dept d
LEFT OUTER JOIN (SELECT dept_id,COUNT(*) AS total FROM emp GROUP BY dept_id) AS e
ON d.id = e.dept_id;
DCL(Data Control Language)数据控制语言
创建用户
create user ‘用户名‘@’ 主机名’ identified by ‘密码’;
注意:
主机名:限定客户端登录ip
指定ip:127.0.0.1
任意ip:%
查看权限
show grants for ‘用户名’@ ‘主机名’;
撤销权限
revoke 权限1,权限2…on 数据库名.表名 from ’ 用户名’ @’ 主机名’
删除用户
drop user ‘用户名’@‘主机名’
密码管理
set password for ‘用户名’@‘主机名’=password(‘新密码’)【超级管理员】
普通用户
set password=password(‘新密码’)
TCL(Transaction Control Language) 事务控制语言
开启事务 start transaction
提交事务 commit
回滚事务 rollback
事务特性
四个属性 | 解释 |
---|---|
原子性:A(atomicity) | 如果一个包含多个步骤的业务,被事务管理,那么这些操作要么同时成功,要么同时失败。 |
一致性:C(consistency) | 事务执行前后,保证数据的完整性 |
隔离性:I(isolation) | 多个事务之间,相互独立,不能干扰 |
持久型:D(durability) | 事务一旦提交,同步到数据库磁盘文件,不可逆 |
事务的隔离性
三种隔离级别 | 解释 |
---|---|
脏读 | 一个事务中,读取到另一个事务未提交的数据(这个在数据库中是不能让它发生的) |
不可重复读 | 一个事务中,二次读取的内容不一致(在进行修改时) |
幻读 | 一个事务中,二次读取的数量不一致(在进行新增和删除时) |
MySQL数据库的隔离级别
级别 | 名字 | 隔离级别 | 脏读 | 不可重复读 | 幻读 | 数据库默认隔离级别 |
---|---|---|---|---|---|---|
一 | 读未提交 | read uncommitted | 是 | 是 | 是 | |
二 | 读已提交 | read committed | 否 | 是 | 是 | Oracle和SQL Server |
三 | 可重复读 | repeatable read | 否 | 否 | 是 | MySQL |
四 | 串行化 | serializable | 否 | 否 | 否 |
数据库慢查询日志
查看慢查询日志开启情况(mysql默认是关闭的)
show variables like ‘%show_query_log%’;
开启慢查询日志
set global show_query_log=on;
查看慢查询时间配置
show variables like ‘%long_query_time’;
修改慢查询的记录时间
set long_query_time=5
注意:
如果设置变量有global全局更改 ,下次打开生效
数据库的索引
– 创建 普通 索引
create index 索引名 on 表名(列名);
– 创建唯一索引
create unique index 索引名 on 表名(列名);
– 创建普通组合索引
create index 索引名 on 表名(列名1,列名2);
– 创建唯一组合索引
create unique index 索引名 on 表名(列名1,列名2);
– 直接删除
drop index 索引名 on 表名;
– 修改表时删除 【掌握】
alter table 表名 drop index 索引名;
– 添加一个主键,这意味着索引值必须是唯一的,且不能为NULL
alter table 表名 add primary key(列名); – 主键索引名 primary
– 添加唯一索引(除了NULL外,NULL可能会出现多次)
alter table 表名 add unique(列名); – 列名就是索引名
– 添加普通索引,索引值可以出现多次。
alter table 表名 add index(列名); – 列名就是索引名
索引的创建原则
- 存储的文本内容可识别率70%以上
- 经常作为条件搜索的字段,建议设置索引
- 经常作为多表主外建连接字段,建议设置索引
- 经常需要排序的字段,建议设置索引
注意:不是所有的字段都适合做索引,创建索引也是需要占用磁盘空间的
索引的失效情况
- 使用like关键字有遵循左前缀匹配规则
- 尽量避免使用or,如果条件有一个没有索引,那么会进行全表扫描
- 在索引列上进行计算
- 在索引列上进行隐式转换
- 使用!=、<>、not in、is not null时
索引的数据结构
有哪些数据结构及特点
- 数组:遍历查找快,适用于内存小量数据
- 链表:增删快,查找慢,适用于内存小量数据
- 二叉树:一个父节点下只有二个子节点,特点:左边子节点比父节点小,右表的子节点比父节点大
- 红黑树:平衡二叉树(左旋和右旋),保证每一个父节点都有二个子节点
- BTree:多路(多叉)平衡搜索树,可以有效控制树的高度
- B+Tree:MySQL用的这个数据结构,(非叶子节点不存储数据,叶子节点没有指针)
- Hash:散列 key-value (无序,根据key查找value超快,范围查找速度慢)
1.7:数组+链表
1.8:数组+红黑树(如果碰撞数量 <8 ,还是使用链表 )
hash碰撞
目的只有一个控制树高度,减少磁盘IO
MySQL中的B+Tree
查看mysql中索引节点的大小
show global status like ‘innodb_page_size’;
MySQL函数
字符串函数
- 函数:CONCAT(s1,s2…sn)
描述:字符串 s1,s2 等多个字符串合并为一个字符串
实例:SELECT CONCAT(“传”, “智”, “播”, “客”);- 函数:CHAR_LENGTH(str)
描述:返回字符串 str 的字符数
实例:SELECT CHAR_LENGTH(“传智播客”);- 函数:LENGTH(str)
描述:返回字符串 s 的字节数
注意:mysql编码UTF8 中文占用3个字节
实例:SELECT LENGTH(“传智播客”) ;- 函数:UCASE(s) | UPPER(s)
描述:将字符串转换为大写
实例:SELECT UCASE(“itcast”);- 函数:LCASE(s) | LOWER(s)
描述:将字符串转换为小写
实例:SELECT LCASE(“ITCAST”);- 函数:LOCATE(s1,s)
描述:从字符串 s 中获取 s1 的开始位置
实例:SELECT LOCATE(‘he’,‘itheima’);- 函数:TRIM(str) | LTRIM(str) | RTRIM(str)
描述:字符串去空格
实例:SELECT TRIM(" 传智人 ");- 函数:REPLACE(s,s1,s2)
描述:将字符串 s2 替代字符串 s 中的字符串 s1
实例:SELECT REPLACE(‘abc’,‘a’,’*’);- 函数:SUBSTR(s, start, length)
描述:从字符串 s 的 start 位置截取长度为 length 的子字符串
实例:SELECT SUBSTR(“itcast”, 2, 3);- 函数:STRCMP(str1,str2)
描述:比较字符串大小,左大于右时返回1,左等于右时返回0,,左小于于右时返回-1,
实例:SELECT STRCMP(“a”,“b”);
日期函数
- 函数:NOW() | CURDATE() | CURTIME()
描述:获取系统当前日期时间、日期、时间
实例:SELECT NOW();- 函数:YEAR(DATE) | MONTH(DATE) | DAY(DATE)
描述:从日期中选择出年、月、日
实例:SELECT YEAR(NOW());- 函数:LAST_DAY(DATE)
描述:返回月份的最后一天
实例:SELECT LAST_DAY(NOW())- 函数:ADDDATE(DATE,n) | SUBDATE(DATE,n)
描述:计算起始日期 DATE 加(减) n 天的日期
实例:SELECT ADDDATE(NOW(),10);- 函数:QUARTER(DATE)
描述:返回日期 DATE 是第几季节(季度),返回 1 到 4
实例:SELECT QUARTER(NOW());- 函数:DATEDIFF(d1,d2)
描述:计算日期 d1->d2 之间相隔的天数
实例:SELECT DATEDIFF(‘2019-08-01’,‘2019-07-01’);- 函数:DATE_FORMAT(d,f)
描述:按表达式 f的要求显示日期 d
实例:SELECT DATE_FORMAT(NOW(),’%Y-%m-%d’);
数据函数
- 函数:ABS(x)
描述:返回 x 的绝对值
实例:SELECT ABS(-1);- 函数:CEIL(x) | FLOOR(x)
描述:向上(下)取整
实例:SELECT CEIL(1.5);- 函数:MOD(x,y)
描述:返回x mod y的结果,取余
实例:SELECT MOD(5,4);- 函数:RAND()
描述:返回 0 到 1 的随机数
实例:SELECT RAND();- 函数:ROUND(x)
描述:四舍五入
实例:SELECT ROUND(1.23456);- 函数:TRUNCATE(x,y)
描述:返回数值 x 保留到小数点后 y 位的值
实例:SELECT TRUNCATE(1.23456,3);
高级函数
case表达式【相当于java中swtich语句】
– 语法
SELECT
CASE [字段,值]
WHEN 判断条件1
THEN 希望的到的值1
WHEN 判断条件2
THEN 希望的到的值2
ELSE 前面条件都没有满足情况下得到的值
END
FROM
table_name;
if表达式
– 语法
SELECT IF(1 > 0,‘true’,‘false’) from table_name;
cast(显示)类型转换【了解】
– 语法
SELECT CAST(参数 AS 类型);
– 类型
字符型:CHAR
日期 : DATE
时间: TIME
日期时间型 : DATETIME
浮点数 : DECIMAL
整数 : SIGNED
数据库的优化
- 硬件:更快的IO,更多的内存
- 系统配置(my.ini):可以通过配置MySQL的一些参数来提高MySQL性能,例如:最大连接数,数据库能占的内存大小,内存使用什么算法,是否支持线程池
- 数据库表结构:
表设计:根据数据三范式来进行表的设计
- 第一范式(1NF)
要求:
每一列不能再拆分- 第二范式(2NF)
要求:
1.一张表只描述一件事情
2.表中的每一个普通列都依赖于主键- 第三范式(3NF)
要求:
从表的外键必须使用主表的主键
表字段类型的选择:
1.选择更小的数据类型(数据库类型越小,占用的磁盘空间,内存和cpu缓存更少)
2.选择简单的数据类型(越简单的数据类型,需要的cpu周期越少,时间,IP都可以用数值类型来表述)
3.尽量避免null,null在查询的时候会比较复杂
4.如果对象数值有进度要求,建议使用decimal
数据库5大约束:
primary key:主键约束(唯一识别一条记录)
unique:唯一索引(数据唯一)
default:默认值(提供默认值)
not null:非空约束(不能为null)
forgein key:设置外键约束
SQL语句的优化:
1.对每一条sql查询都进行优化,尽量避免全表扫描(explain sql 查询语句),考虑在where子句后或者order by 后的列进行建立索引
2.在where子句后尽量避免对null值的判断,以及!=,or,in,ont in,like,表达式函数,这些操作会导致放弃索引查询,而采用全表扫描
3.不要在where子句=左边进行函数,算数运算或者其他的表达式运算,否则MySQL就无法正确的使用索引
4.在使用索引查询时,如果是多列索引,必须要使用最左前缀,没有使用,就会用全表扫描
5.不要写没有意义的查询
来源:oschina
链接:https://my.oschina.net/u/4283164/blog/4304299