
知识点
事务
———————
**事务是是指一组sql语句组成的数据库逻辑处理单元,在这组的sql操作中,要么全部执行成功,要么全部执行失败。
--事务的特性 (ACID)
1. 原子性 (Atomicity):所有操作全部完成或全部不完成,最小的执行单位。undo log
2. 一致性 (Consistency):事务执行前后都处于一致性状态。redo log
3. 隔离性 (Isolation):并发执行的各个事务之间不能互相干扰。S/X锁+MVCC
4. 持久性 (Durability):事务执行完对数据的修改是永久的。
--Redo/Undo机制
1. Redo log记录被修改后的值,用来恢复未写入 data file 的更新成功的数据;
2. Undo log记录数据更新前的值,保证数据更新失败能够回滚。
--事务隔离级别
**默认隔离级别: (select @@transaction_isolation;)
1. 读未提交(Read Uncommitted):一个事务读到另一个事务未提交读数据。读不加锁,写加排它锁。
2. 读已提交(Read Commited):一个事务修改的数据提交后才能被另外一个事务读取。每次select生成MVCC版本。
3. 可重复读(Repeatable Read):保证一个事务相同条件下前后两次获取的数据是一致的。第一次select生成MVCC版本。
4. 串行化(Serializable):每次读操作都会加锁,快照读失效,事务串行执行。读加共享锁,写加排它锁
--为什么选读已提交作为事务隔离级别
1. 可重复读存在间隙锁,导致出现死锁的几率比RC大的多!
2. 可重复读条件列未命中索引会锁表!而在RC隔离级别下,只锁行
3. 在RC隔离级别下,半一致性读(semi-consistent)特性增加了update操作的并发性!
--并发(事务)问题
1. 脏读:读取被更新但没提交的字段
2. 不可重复读:T1读取了字段,然后T2更新UPDATE了该字段并提交之后,T1再次提取同一个字段,值便不相等
3. 幻读:事务T1从表中读取数据,然后T2进行了INSERT操作并提交,当T1再次读取的时候,结果不一致的情况发生
--锁
1. 共享锁/读锁:SELECT ... LOCK IN SHARE MODE;
2. 排它锁/写锁:SELECT ... FOR UPDATE;
3. 间隙锁:Gap Locks和Next-Key Locks
4. 行锁 5. 表锁 6. 悲观锁 7. 乐观锁
**MySQL 把行锁和间隙锁合并在一起,解决并发写和幻读的问题,这个锁叫做 Next-Key锁
**串行化时,读的时候加共享锁,写的时候加排它锁
**读未提交:读不加任何锁,写加排它锁
存储引擎
———————
MyISAM/InnoDB
1. myisam只支持表级锁,不支持事务、外键,支持全文索引;非聚簇索引(叶子节点存指针)
2. Innodb支持行级锁、事务、外键,不支持全文索引;聚簇索引。通过MVCC(多版本并发控制)解决了幻读问题。
3. myisam本身存储了表的总数据行,Innodb没有存储,查总行数myisam更快,如果加了查询条件两者就没有区别了
InnoDB四大特性:1. 插入缓冲;2. 二次写;3. 自适应哈希索引;4. 预读;
索引
————————————
**索引是一种数据结构。索引中是包含一个表中列的值和它的物理地址的值,并且这些值存储在一个数据结构中。
--优点(检索快,减少I/O次数;加快分组和排序;保证数据唯一性、表间参照完整性)
1. 加快数据检索 (定位快)
2. 保证数据的唯一性 (唯一约束)
3. 实现表与表之间的参照完整性(进行外键约束参照的列)
4. 在使用group by、order by 字句进行查询时,利用索引可以减少排序和分组的时间
--缺点(时间空间,减慢增删改)
1. 创建索引会需要一定的时间和数据空间。
2. 虽然创建索引增加了查询的速度,但是减慢了增删改的速度
**B树索引/哈希索引
1. B树索引具有范围查找和前缀查找的能力,复杂度为O(LogN)。
2. 哈希索引只能做等值查找,复杂度都是O(1)。
--聚簇索引/非聚簇索引
1. 聚簇索引:叶子节点中存放整行数据(数据页),一般是主键索引或非空的唯一索引
2. 非聚簇索引(辅助索引):存放的是索引(主键值),指向专门的数据页的数据
--聚簇索引的优缺点
优点:
1. 数据访问更快:因为聚簇索引将索引和数据保存在同一个B+树中
2. 聚簇索引对于主键的排序查找和范围查找速度非常快
缺点:
1. 插入速度严重依赖于插入顺序:按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
2. 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
3. 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
--逻辑角度
1. 普通索引:仅加速查询
2. 唯一索引:加速查询 + 列值唯一(可以有null)
3. 主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个(聚簇索引)
4. 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
5. 外键索引:保证数据的一致性、完整性和实现级联操作
6. 全文索引:用大文本对象的列构建的索引
--不推荐使用索引(没必要用)
1. 数据唯一性差(一个字段的取值只有几种时,比如性别)
2. 频繁更新的字段
3. 字段不在where语句
4. 使用不等于(<>)
--索引失效的情况(没用)
1. 条件中有or:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2. 组合索引:未使最左边的字段(最左前缀原则)
3. like查询以%开头,前导模糊查询不能利用索引
4. 存在索引列的数据类型隐形转换。(1. 列类型是字符串未用引号;2. 索引列上有数学运算;3.使用函数)
5. mysql估计全表扫描更快 ( 比如数据量极少)
**索引失效分析工具:explain命令加在sql语句前面,在执行结果中查看key这一列的值,如果为NULL,说明没有使用索引
--主键和唯一索引的区别
**主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别
1. 主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;
2. 主键不允许为空值,唯一索引列允许空值;
3. 一个表只能有一个主键,但是可以有多个唯一索引;
4. 主键可以被其他表引用为外键,唯一索引列不可以;
--主键、外键和索引
1. 主键:唯一标识一条记录,不能有重复的,不允许为空;用来保证数据完整性;主键只能有一个
2. 外键:表的外键是另一表的主键, 外键可以有重复的, 可以是空值;用来和其他表建立联系用的,保证一致性;可以有多个外键
3. 索引:该字段没有重复值,但可以有一个空值;是提高查询排序的速度;一个表可以有多个惟一索引
**覆盖索引:索引包含所有满足查询需要的数据,即不需要回表操作,可以优化Limit分页查询的效率
范式
————————————
1. 第一范式:原子性,字段不可分;数据库表中的任何属性都具有原子性的,不可再分解
2. 第二范式:唯一性,有主键且非主键字段依赖主键;对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性
3. 第三范式:非主键字段不能相互依赖;对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余
视图
————————————
**视图本质上是一种虚拟表。
--优点(简化sql查询,提高开发效率)
1. 简单化,数据所见即所得
2. 安全性,用户只能查询或修改他们所能见到得到的数据
3. 逻辑独立性,可以屏蔽真实表结构变化带来的影响
--缺点
1. 性能相对较差,简单的查询也会变得稍显复杂
2. 修改不方便,特变是复杂的聚合视图基本无法修改
查询语言分类
————————————
1. 数据查询语言DQL:SELECT子句,FROM子句,WHERE子句
2. 数据操纵语言DML:INSERT,UPDATE,DELETE
3. 数据定义语言DDL:表、视图、索引、同义词、聚簇等,DDL是隐性提交的,不能rollback,create, drop
4. 数据控制语言DCL:设置或者更改数据库用户或权限的语句,包括GRANT、DENY、REVOKE
删除表
————————————
1. delete : 仅删除表数据,支持条件过滤,支持回滚。记录日志。因此比较慢。
2. truncate: 仅删除所有数据,不支持条件过滤,不支持回滚。不记录日志,效率高于delete。
3. drop:删除表数据同时删除表结构。将表所占的空间都释放掉。删除效率最高。
in/not in/exists/not exists
————————————
1. not exist会对主子查询都会使用索引
2. exist会针对子查询的表使用索引
3. in与子查询一起使用的时候,只针对主查询使用索引
4. not in则不会使用任何索引
**子查询表大的用exists,子查询表小的用in;not exists比not in 快
--游标
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理。
--存储过程
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。
--触发器
触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。
binlog
————————————
--录入格式
1. statement:保存修改数据的sql语句
2. row:保存修改的记录
3. mixed
技巧
--sql执行顺序
1. from 2. join……on 3. where 4. group by 5. avg,sum.... 6. having
7. select 8. distinct 9. order by 10. limit
--[LIMIT N][ OFFSET M]=limit m,n。limit是在order之后执行的。offset m不包括m,既limit 0,1=limit 1 offset 0=limit 1。
--去重,distinct。group by 可替代distinct。
--inner join...on... 输出两表共同的,可用where直接代替
--在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与聚合函数(group by)一起使用。HAVING 子句可以让我们筛选分组后的各组数据。
--精确匹配采用=,范围请用in/not in
--sum(amount) over(partition by name order by mon rows between unbounded preceding and current row)
--排序
1. rank():并列,占位
2. dense_rank():并列,不占位
3. row_number() over():不并列,row_number() over([partition by sex] order by age desc) as rank
--求top1/topN
1. 自链接(推荐)
SELECT a.*,b.max_score from sc a
INNER JOIN (
SELECT CId,max(score) max_score
from sc
GROUP BY CId ) b
on a.CId= b.CId and a.score= b.max_score;(每门课程中成绩最好的人)
2. 自查询(数据量不能大)
SELECT * from sc a
where score = (SELECT max(score) from sc where a.CId=CId )
3. EXISTS
SELECT * from sc a where
not EXISTS
(SELECT 1 from sc where a.score <score and a.CId= CId)
4. 窗口函数(推荐)
SELECT SId ,CId,score from (
SELECT SId,CId,score,dense_rank() over (partition by CId ORDER BY score desc) as ranking from sc ) b
where ranking=N; (更改此处条件可随性求top N, top1-N等)
--字符串连接
1. concat(s1, s2, ...)
2. concat_ws(x, s1, s2, ...) 有分割符x
3. group_concat(): 连接字段,多个值显示为一行;group_concat( [DISTINCT] 连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
--字符串截取
1. left(str, length)
2. right(str, length)
3. substring(str, index[, len]) index>0从左边开始, index<0从右边开始;(sql索引从1开始)
4.
--查询用户的最长连续登陆天数
select uid, max(continuous_days) as maxday from
(
select uid, date_sub(date1,sort) as login_group, count(*) as continuoous_days from
(
select uid,udate, row_number() over(patition by uid order by udate) as sort from user_login
) a
group by uid, login_group
) b
group by uid;
版权所有,翻版不究。