MySQL
SQL语言及其分类
SQL:结构化查询语言,SQL是一套标准
MySQL常用命令
# 退出
exit;
# 展示所有数据库
show databases;
# 使用某个数据库
use dataBaseName;
# 创建数据库
create database dataBaseName;
数据库中最基本的单元是表(table),任何一张表都有行和列
- 行(row):被称为数据/记录
- 列(col):被称为字段
SQL语句有很多,如下
- DQL:数据查询语言select
- DML:数据操作语言,对表中的数据进行增删改
- insert 增
- delete 删
- update 改
- DDL:数据定义语言,对表的结构进行更改
- create 增加
- drop 删除
- alter 修改
- TCL:事务控制语言
- 事务提交 commit
- 事务回滚 rollback
- DCL:数据控制语言
- 授权 grant
- 撤销权限 revoke
# 查询表中数据
select * from tableName;
# 查看表的结构
desc tableName;
# 查看数据库版本号
select version();
# 终止一条命令的输入
\c
# 退出进程
\q
简单查询
select 字段名 from 表名;
# 查询所有数据
select * from myTable;
条件查询
select 字段名 from 表名 where 条件;
select * from myTable where id > 2;
条件:
-
等于、不等于、小于等于、大于等于、大于、小于
-
between… and… :两个值之间
-
is null:值为null
-
and:并且
-
or:或者
-
in:包含
-
not:取非,主要用于is和in上
-
like:模糊查询,支持%或下划线匹配
-
%:匹配任意个字符
-
下划线:任意一个字符
-
select * from myTable where name like '%0'; # 找出name中以0结尾的
排序
select 字段名 from 表名 order by 字段名;
默认是升序
# 默认升序
select * from myTable order by good;
# 指定降序
select * from myTable order by good desc;
# 指定升序
select * from myTable order by good asc;
多个字段排序
# 表示在good相同的情况下,按bood排序,越前面的就越起得主导作用
select * from myTable order by good asc, bood asc;
数据处理函数
单行处理函数:一个输入对应一个输出。和单行处理函数相对的是多行处理函数(多个输入对应一个输出)
单行处理函数
- lower 转换小写
- upper 转换大写
- substr 取子串
- length 取长度
- trim 去空格
- str_to_date 将字符串转换成日期
- data_format 格式化日期
- format 设置千分位
- round 四舍五入
- rand() 生成随机数
- ifnull 转换成一个具体值
使用
select lower(name) from myTbale;
多行处理函数
多行处理函数:多个输入对应一个输出
- count 取得记录数
- sum 求和
- avg 取平均
- max 取最大值
- min 取最小值
分组函数自动忽略null
分组查询
在实际的应用中,需要先进行分组,再对每一组的数据进行操作
select ... from ... group by ...
select … from … where … group by … order by…
执行顺序为
from(表) -> where(过滤) -> group by(分组) -> select(查询) -> order by(排序)
为什么分组函数不能直接使用在where之后?
因为分组函数在使用的时候必须先分组才能使用,分组函数的本质是先执行了一个group by才执行相应的函数的。
关键字distinct
select ename, distinct job from eop;# 去除重复记录
连接查询
从一张表中单独查询,称为单表查询。而对于跨表查询,多张表进行联合的查询数据,称为连接查询
内连接
外连接
全连接
笛卡尔积的匹配次数的呈现指数型增长的,时间复杂度较高。
通过笛卡尔积现象得出,表的连接次数越高效率越低,尽量避免
子查询
select语句中嵌套select语句称为子查询
select ... (select) from ... (select) where ... (select)
用法
# 找出大于最低工资的员工
# 找出最低工资
select min(sal) from emp; # 800
# 找出大于最低工资员工
select ename, sal from emp where sal > 800;
# 合并
select ename, sal from emp where sal > (select min(sal) from emp);
关键字union
select ename, job from emp where job = 'a' or job = 'b';
select ename, job from emp where job in 'a' or job in 'b';
select ename, job from emp where job = 'a' union select ename, job from emp where job = 'b';
关键字limit:将查询结果集的一部分取出来,通常使用在分页查询中
limit start, last
select ename, job from emp where job = 'a' or job = 'b' limit 0, 5;
limit的执行顺序是在order by之后
DML和DDL
建表
create table tableName (
dataName dataType,
dataName dataType,
dataName dataType,
dataName dataType
);
数据类型
varchar 可变长度字符串。需要动态分配,速度慢
char 定长字符串。不需要动态分配,速度快
int 整数
bigint 长整型
float
double
date 短日期
datatime 长日期
clob 字符大对象 4G
blob 二进制大对象 可以存储如图片,视频等等
删除表
drop tableName; # 当这张表不存在的时候会报错
drop table if exists tableName;
插入数据
insert into tableName (dataName, dataName, dataName) values (data, data, data);
一次性插入多条数据
insert insert into tableName (dataName, dataName, dataName) values
(data, data, data),
(data, data, data)
(data, data, data);
更新数据
update tableName set dataName1=data, dataName2=data where id = 1;# 没有where会导致所有全部更新
删除数据
delete from tableName where id=1;
多表查询的条件on
加条件只是为了避免笛卡尔积的现象,只是为了查询出有效的组合记录,匹配的次数一次都没少
select e.a, p.b from e join p on e.g = p.g;
delete的数据被删除了,但是这个数据在硬盘上的真实存储空间不会被释放
优点:删除效率比较低
缺点:支持回滚,后悔了可以再恢复数据
rollback;
truncate from tableName where id=1;
# DDL语句
# 不支持回滚
快速创建表
将查询结果当作一张表创建
create table emp as select * from empd;
将查询结果插入一张表
insert into dp select * from empd;
对表结构的增删改
alter
约束
约束对应的英语单词:constraint
在创建表的时候,我们可以给表中的字段加上一些约束,来保证这个表中数据的完整性、有效性!
约束的作用就是为了保证:表中的数据有效!!
非空约束
not null
唯一性约束
unique
主键约束
primary key
主键分类
- 自然主键:主键值是一个自然薮,和业务没关系-
- 业务主键:主键值和业务紧密关联,例如拿银行卡账号做主键值。这就是业务主键!
建议使用数值类型
外键约束
foreign key
当cno字段没有任何约束的时候,可能会导致数据无效,因此要绑定另一个表的相关联字段
子表中的外键引用的父表中的某个字段,被引用的这个字段必须是主键吗?
不一定是主键,但至少具有unique约束。外键可以为NULL吗?
外键值可以为NULL.
检查约束
check # mysql 不支持,Oracle支持
存储引擎
存储引擎是MySQL中特有的一个术语,其它数据库中没有。
实际上存储引擎是一个表存储/组织数据的方式。
不同的存储擎,表存储数据的方式不同。
# 默认存储引擎是innodb,默认字符集的utf8
create table tableName (
dataName dataType,
dataName dataType,
dataName dataType,
dataName dataType
)engine=innodb default charset=utf8
MySQL存储引擎
mysql> show engines \G
*************************** 1. row ***************************
Engine: ARCHIVE
Support: YES
Comment: Archive storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 3. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4. row ***************************
Engine: FEDERATED
Support: NO
Comment: Federated MySQL storage engine
Transactions: NULL
XA: NULL
Savepoints: NULL
*************************** 5. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 6. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
*************************** 7. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 8. row ***************************
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 9. row ***************************
Engine: CSV
Support: YES
Comment: CSV storage engine
Transactions: NO
XA: NO
Savepoints: NO
9 rows in set (0.02 sec)
常用存储引擎
MYIASM
它管理的表具有以下特征:
-
使用三个文件表示每个表:
-
格式文件―存储表结构的定义(mytable .frm)
-
数据文件―存储表行的内容(mytable.MYD)
-
索引文件一存储表上索引(mytable.MYI)
-
对于一张表来说,只要是主键或者加上unique的字段,就会产生索引
-
-
可被转换为压缩、只读表来节省空间
-
MyISAM不支持事务机制,安全性低
InnoDB
InnoDB支持事务,支持数据库崩溃后自动恢复机制(非常安全)
它管理的表具有以下特征:
- 每个InnoDB 表在数据库目录中以.frm格式文件表示InnoDB
- 表空间tablespace被用于存储表的内容(表空间是一个逻辑名称,存储数据+索引)
- 提供一组用来记录事务性活动的日志文件
- COMMIT(提交)、SAVEPOINT及ROLLBACK(回滚)支持事务处理提供全AcID兼容
- 在MySQL服务器崩溃后提供自动恢复多版本(mvcc)和行级锁定
- 支持外键及引用的完整性,包括级联删除和更新
InnoDB最人的特点就是支持事务:以保证数据的安全。效率不是很高,并且也不能压缩,不能转换为只读,不能很好的节省存储空间.
此处提及一下mvcc,主要是前几天面试被问到了,做个笔记
MVCC
,全称Multi-Version Concurrency Control
,即多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。MVCC 在 MySQL InnoDB 中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读
事务
一个事务其实就是一个完整的业务逻辑。要么同时成功,要么同时失败,不可再分。
只有DML和事务有关(insert update delete)
到底什么是事务呢?
说到底,说到本质上,一个事务其实就是多条DM语句同时成功,或者同时失败!
提交事务:commit
回滚事务:rollback
关闭MySQL的自动提交机制(MySQL默认开启自动提交事务机制)
start transaction;
事务四个特性
- 原子性:说明事务是最小的工作单元。不可再分
- 一致性:所有事务要求,在同一个事务当中,所有操作必须同时成功,或者同时失败,以保证数据的一致性。
- 隔离性A事务和B事务之间具有一定的隔离。教室A和教室B之间有一道墙,这道墙就是隔离性。A事务在操作一张表的时候,另一个事务B也操作这张表会那样
- 持久性事务最终结束的一个保障。事务提交,就相当于将没有保存到硬盘上的数据保存到硬盘上
事务隔离级别
-
读未提交:read uncommitted(最低的隔离级别)---------》脏读(一般不会出现)。
-
读已提交:read comnitted ---------》解决了脏读,在事务开启之后,第一次读到的数据是3条,当前事务还没有结束,可能第二次再读取的时候,读到的数据是4条,导致不可重复读。
-
可重复读:repeatable read(读到的是重复副本数据、数据库默认隔离级别) ---------》事务A开启之后,不管是多久,每一次在事务A中读取到的数据都是一致的。即使事务B将数据已经修改,并且提交了,事务A读取到的数据还是没有发生改变,这就是可重复读。解决了不可重复读,导致了幻读。
-
序列化/串行化:serializable(最高的隔离级别) ---------》这是最高隔离级别,效率最低。解决了所有的问题。试种隔离级别表示事务排队,不能并发
索引
索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。
如果没有添加索引则会全局扫描,效率较低
MysQL在查询方面主要就是两种方式:
- 第一种方式:全表扫描
- 第二种方式:根据索引检索
在mysql数据库当中索引也是需要排序的,并且这个所以的排序和Treeset薮据结构相同。Treeset底层是一个自平衡的二叉树,在mysql当中索引是一个B-Tree数据结构
因为只有排序了才会有区间杳找这一说,缩小扫描范围就是扫描某个区间
索引实现原理
假设有一张用户表
id(PK) name 每一行记录在硬盘上都有物理存储编号
100 liuhao 0x1000
120 yanjing 0x1111
提醒1:在任何数据库当中主键上都会自动添加索引对象,id字段上自动有索引,因为id是PK。另外在mysql当中,一个字段上如果有unique约束的话,也会自动创建索引对象。
提醒2:在任何数据库当中,任何一张表的任何一条记录在硬盘存储上都有一个硬盘的物理存储编号。
提醒3:在mysql当中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在MyISAM存储引擎中,索引存储在一个.MYI文件中。在InnoDB存储引擎中索引存储在一个逻辑名称叫做tablespace的当中。在MEMORY存储引擎当中索引被存储在内存当中。不管索引存储在哪里,索引在mysql当中都是一个树的形式存在。(自平衡二叉树:B-Tree)
select * from t_user where id = 101;
mysql发现id字段上有索引对象,所以会通过索引对象idIndex进行查找通过idIndex索引对象定位到:101(缩小扫描范围,快速定位)
通过101得出物理编号∶Ox6666,此时马上SQL语句转换∶
select * from t_user where物理编号=0x6666;
创建索引
# 给emp表的ename字段添加索引
create index emp_ename_index on emp(ename);
删除索引
# 给emp表的ename字段删除索引
drop index emp_ename_index on emp(ename);
查看索引
explain xxx
索引失效
-
模糊匹配的时候用%开始
-
使用or的时候如果其中一边有一段字段没有索引,那么另一个字段的索引也会失效(不建议使用or的原因)
-
使用复合索引的时候,没有使用左侧的列查找,索引失效
-
复合索引:两个字段,或者更多字段联合起来添加一个索引,叫做复合索引
create index emp_ename_index on emp(ename, eno);
-
-
在where中索引列参与了运算
-
# 索引列参与了运算 select * from enamp where sal + = 100;
-
-
在where中索引列使用了函数
聚集索引(主键索引、聚簇索引)和辅助索引(二级索引、非聚簇索引)
聚集索引(主键索引):
- 聚集索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的记录数据。
- 聚集索引的叶子节点称为数据页,聚集索引的这个特性决定了索引组织表中的数据也是索引的一部分。
辅助索引(二级索引):
-
非主键索引,叶子节点=键值+书签。Innodb存储引擎的书签就是相应行数据的主键索引值。辅助索引,其叶子节点并不包含行记录的全部数据,叶子结点除了包含键值以外,每个叶子结点中的索引行还包含了一个书签,该书签用来告诉存储引擎可以在哪找到相应的数据行,由于innodb引擎表是索引组织表,因此innodb存储引擎的辅助索引的书签就是相应行数据的聚集索引键
-
一个表中的所有索引除了聚集索引,其他的都是二级索引(secondary index)
-
由于辅助索引只存储主键的值,如果使用辅助索引搜索数据就必须先从辅助索引取到主键的值,再使用主键的值去主键索引上查询,直到找到叶子节点上的数据返回。 ---- 这个也称之为回表
Hash 索引任何时候都避免不了回表查询数据,而 B+ 树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询;
索引分类
-
单一索引:一个字段上添加索引
-
复合索引:两个字段或者更多的字段上添加索引-主键索引:主键上添加索引
-
唯一性索引:真有unique约束的字段上添加索引
-
全文索引:对文本的内容进行分词,进行搜索
-
覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖
-
不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引的列,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引.
如果辅助索引上已经存在我们需要的数据,那么引擎就不会去主键上去搜索数据了。 ---- 这个就是所谓的"覆盖索引"
并不是所有的索引都可以成为辅助索引
注意:唯一性比较弱的字段上添加索引用处不大
-
最左前缀匹配原则
在 MySQL 建立 联合索引(多列索引) 时会遵守最左前缀匹配原则,即 最左优先,在检索数据时从联合索引的最左边开始匹配。例如有一个 3 列索引(a,b,c),则已经对(a)、(a,b)、(a,b,c)上建立了索引。所以在创建 多列索引时,要根据业务需求,where 子句中 使用最频繁 的一列放在最左边。
根据最左前缀匹配原则,MySQL 会一直向右匹配直到遇到 范围查询(>、<、between、like)就停止匹配。
注意这是MySQL的,Oracle不是这样的,Oracle任意顺序都可以。
视图
假设有一条非常复杂的SQL语句,而这条SQL语句需要在不同的位置上反复使用。每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办?
可以把这条复杂的SQL语句以视图对象的形式新建。
在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。
并且利于后期的维护,因为修改的时候也只需要修改一个位置就行,只需要修改视图对象所映时的SQL语句。
我们以后面向视图开发的时候,使用视图的时候可以像使用table一样。可以对视图进行增删改查等操作。视图不是在内存当中,视图对象也是存储在硬盘上的,不会消失
DBA
不做概述
数据库范式
- 第一范式:要求任何一张表必须有主键,每一个字段原子性不可再分。
- 第二范式:建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖-
- 第三范式:建立在第二范式的基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖。
还有一种是在另一个地方看到的
- 第一范式:每一个字段原子性不可再分,即二维表。
- 第二范式:建立在第一范式的基础之上,拥有主键
- 第三范式:建立在第二范式的基础之上,要求所有非主键字段直接依赖主键