数据库Mysql
内容管理
- 数据库基础
- 什么是DB、DBMS、DBS、DBA?
- 什么是元组、码、候选码、主、外码(键)、(非)主属性?
- 主、外码的区别?
- 为什么不推荐使用外码和级联 ?【分布式高并发】
- 什么是E-R?
- 数据库范式?
- 存储过程,不推荐?
- drop、delete、truncate?
- 数据库设计步骤?
- Mysql
- Mysql架构,一条SQL在Mysql执行流程?
- MySQL存储引擎架构?
- MyISAM和InnoDB?
- MySQL数据类型和场景
- SQL语句类型?
- SQL约束?
- 子查询?
- 左右全连接?
- in和exists区别?
- UNION和UNION ALL区别?
- 临时表?
- 为什么要主键,使用auto还是UUID?
- 字段为什么NOT NULL
- SQL语句执行顺序?
- 可以用MySQL存储图片?
- 索引
- 什么是索引?
- 索引一定好?
- 索引数据结构? Hash和B+区别?
- B和B+区别,为什么使用B+?
- 聚簇索引和非聚簇索引?
- 非聚簇索引一定会回表查询?
- 索引类型(结构)?
- 索引种类
- 索引覆盖
- 什么是前缀索引,最左匹配原则?
- 索引设计原则
- 索引失效的情况?
- 索引优化?
- 数据库事务
- 数据库四大特性:
- 数据库并发一致性问题:
- 数据库隔离级别:
- MySQL隔离级别是基于数据库锁实现?MVCC
- 当前读和快照读?
- 什么是MVCC?
- 数据库 锁
- 数据库隔离级别和数据库锁的关系?
- 数据库锁的类型?
- 什么是乐观锁、悲观锁?
- 什么时意向锁?
- InnnoDB行级锁类别?
- InnoDB行级锁使用注意?
- 死锁? MySQL如何避免?
- 数据库优化
- SQL执行很慢原因?
- 慢查询? 如何优化?
- 查询过程数据访问如何优化?
- 长难查询语句如何优化?
- 如何优化LIMIT分页?
- 如何优化UNION?
- 如何优化where?
- 大表数据查询如何优化?
数据库MySQL的相关知识简洁汇总
之前的所有博客都是分享类型,内容多而基础浅显,这里将本人的bg汇总
数据库基础
数据库基础大多是抛开具体的数据库来谈的基础概念,cfeng试水的rk数工就是考察的详细的数据库基础,而不是考察具体的数据库语言
什么是DB、DBMS、DBS、DBA?
DB: 数据的集合、DBMS管理数据的集合
DBMS: 操作和管理数据的软件
DBS:软件、数据库、DBA的集合
DBA: 全面管理和控制DBS
什么是元组、码、候选码、主、外码(键)、(非)主属性?
数据库基础概念:
元组: 每一行(记录)就是一个元组
码: 唯一标识实体的属性,对应表中的列
候选码: 所有可以唯一标识实体的属性(属性组) — 属性组其子集不能唯一标识
主码: 候选码中选取一个属性(组)作为主码, 唯一标识
外码: 当前关系中一个属性是两外一个关系的主码,该属性为外码
主属性: 候选码中出现过的属性
非主属性: 除开主属性之外的属性
主、外码的区别?
主码: 唯一标识一个元组, 自带约束UNIQUE和NOT NULL,一个表只能一个
外码: 与其他关系建立联系,可以为空,可以重复,一个表可以有多个外键
应用开发中不推荐使用外码和级联
为什么不推荐使用外码和级联 ?【分布式高并发】
单机低并发情况推荐使用外码、级联,分布式、高并发不推荐使用(cfeng的offerCampus项目也是考虑到后期的复杂性,就直接服务调用填补)
外码的优势: 保证数据库数据一致性(不会不准确)和完整性,级联操作方便
- 增加复杂性: 每次做UPDATE和DELETE操作必须考虑外码,测试时可能经常失败; 同时外码导致主从关系固定,不能适应变化
- 增加维护难度: 需要额外维护外键
- 分库分表不生效:分布式条件下分库外码不生效
什么是E-R?
E-R 实体-联系图,数据库设计中表示概念关系模式的一种方式 【表示方法:…菱形、矩形、线…]
数据库范式?
1NF: 属性原子性、不可再分,所有关系型数据库都满足
2NF: 1NF基础上不存在非主属性对码的部分函数依赖
3NF: 2NF基础上不存在非主属性对码的传递函数依赖
BCNF: 3NF基础上不存在主属性对码的部分、传递函数依赖
存储过程,不推荐?
存储过程类似编程语言的函数,是SQL语句的集合,可以用于处理复杂的业务逻辑(还可以生成亿级数据),可以携带参数,调用使用call()方式
存储过程比纯SQL执行更快,因为其预编译过
不推荐使用存储过程,因为其难以调试扩展,无移植性、消耗数据库资源
drop、delete、truncate?
drop用于删除表或者库,truncate用于情况表的数据,delete用于删除表中数据
属于不同的语言: drop和truncate属于DDL, delete属于DML,可以回滚
执行速度:drop 》 truncate 》 delete;
数据库设计步骤?
需求分析 : 分析需求
概念设计: E-R
逻辑设计: 关系模式
物理设计: 选择合适的存储结构
数据库实施: 编程
数据库运行维护: 维护、日志
Mysql
Mysql是一个开源的轻量级的关系型数据库,持久化存储用户数据,默认端口号3306,使用的协议…
Mysql架构,一条SQL在Mysql执行流程?
Mysql架构分为server层和存储引擎层,Server层包括连接器、分析器、优化器、执行器、binlog日志(主从复制); 存储引擎层负责进行数据的存储读取(磁盘)
- 连接器: 身份认证,管理连接; 和客户端交互相关
- 查询缓存: Mysql8之后移除,因为缓存使用语言中的缓存即可
- 分析器: 词法分析和语法分析,识别功能和相关Error
- 优化器: 索引选择,优化(所以联合索引where后的顺序不影响),按照MySQL认可的方案执行
- 执行器: 执行语句,从存储引擎返回数据,【执行前会鉴权】
- 存储引擎: 采用插件式架构(即插即用),数据的存储读取(磁盘)
MySQL存储引擎架构?
MySQL存储引擎架构方式为插件式引擎,存储引擎是基于表的,而不是数据库,也就是可以为不同的表选择不同的存储引擎;
Mysql5之前默认的存储引擎是MyISAM, 之后默认的都是InnoDB
MyISAM和InnoDB?
- 行级锁: MyISAM只支持表级锁,InnoDB支持行级锁,MyISAM在并发条件下一下就锁住整张表(性能!)
- 事务: InnoDB是事务性存储引擎,只有InnoDB支持事务,其他引擎包括MyISAM都不支持
- 外码: InnoDB支持外码,MyISAM不支持(虽然不推荐使用)
- 安全恢复: MyISAM在数据库异常崩溃后,不能安全恢复,InnoDB依靠redo可以
- MVCC: MVCC是行级锁的升级,MyISAM也不支持
- 表结构: InnoDB中数据和索引集中存储,而MyISAM分开存储,数据.myd,索引.myi 【InnoDB中为聚簇索引,MyISAM为非聚簇索引】
MySQL数据类型和场景
整数: Mysql支持隐式转换,将String转为Int; TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT分别占用8、16、24、32、64; INT(10)中10只表示显示字符的个数,无实际意义 【VARCHAR中的10是存储字符的个数】
浮点数: FLOAT、DOUBLE、DECIMAL; 一般金额采用DECIMAL
字符串:VARCHAR和CHAR; VARCHAR可变长,更节省空间,但是应该是时间换取空间
日期: YEAR、TIME、DATE、DATETIME、TIMESTAMP; TIMESTAMP相比DATETIME空间利用率更高
SQL语句类型?
DQL、DDL、DML、DCL
SQL约束?
主键约束、外键约束 、唯一约束、非空约束、CHECK约束
子查询?
将一个查询结果在另外一个查询中使用
按照子查询结果类型:
- 标量子查询: 子查询返回结果为一个值,使用= >= …
- 列子查询: 子查询为一列结果,那么就可以用not in…
- 行子查询: 子查询结果为一行的记录, 就可以使用(XX,XX) = …
- 表子查询: 拆线呢结果为n行m列的表
左右全连接?
内连接只是显示重合的列
就是笛卡尔积显示数据以XX为准,比如左外连接就显示左表中全部的列,右外就是右表,全就是全部…
in和exists区别?
- 使用上: in查询字段只能一个,exists可以多个
- 原理:in是将外表和内表作hash连接,exists对外表作loop循环
所以当外表数据较大,那么建议使用in,如果较少,使用exists
UNION和UNION ALL区别?
union和union all都是合并查询结果集
union会对结果去重排序,union all直接返回合并结果,所以union all更快
临时表?
MySQL执行SQL语句会创建存储中间结果集的临时表,对当前连接可见,连接关闭消失
临时表分为内存临时表和磁盘临时表: 内存临时表基于MEMORY引擎,磁盘临时表基于MyISAM引擎
比如在form子查询、distinct的order by、union等会使用临时表
为什么要主键,使用auto还是UUID?
主键是唯一表示一行记录,没有主键标识将会很困难
使用自增ID,主键的长度更短,不需要手动维护,但是缺点就是不容易进行数据库迁移,表合并麻烦,容易被有心人获取到业务量
使用UUID,主键长度会很长,影响查询速度,占用空间大,但是不用担心业务量泄露,可以在应用层生成,提高数据库的吞吐能力
MySQL默认使用的就是Auto,因为主键索引是聚簇索引,B+树的叶子节点按顺序存储了主键值和数据,auto就只需要项后排即可, 但是UUID随机生成,插入时会造成大量数据移动,产生内存碎片,性能低
字段为什么NOT NULL
NULL是占用空间的,B树不存储Null,所以索引用不到null,Count统计不会统计NULL值,会造成数据统计不上,影响结果
SQL语句执行顺序?
SQL语句 —> FROM ----> ON —> JOIN —> WHERE —> GROUP BY —> HAVING --> SELECT —> DISTINCT —> ORDER BY ----> LIMIT
关键就是where在order by之前,所以分组后要过滤只能having
可以用MySQL存储图片?
可以是可以,使用二进制文件即可,也就是BLOB大对象即可,但是不推荐直接存储文件,会严重影响数据库性能,消耗过多存储空间,一般就存储一个路径即可,对象存储可以采用第三方服务比如MinIO…
索引
索引是一种数据库结构
创建索引: CREATE INDEX index_name ON table_name(col_name)
创建表时创建索引:
CREATE TABLE XX(FULLTEXT KEY (information))
使用ALTERE TABLE 创建:
ALTER TABLE table_name ADD INDEX index_name (colum_list)
删除主键索引: ALTER TABLE table_name DROP PRIMARY KEY
删除其他索引: ALTER TABLE table_name DROP KEY index_name
什么是索引?
索引INDEX是对数据库表中一列或者多列联合进行排序的一种数据库结构,就像书本的目录
索引一定好?
索引的优点就是 可以大大加快数据检索速度, 加速表连接、将随机IO变为顺序IO(B+树叶子连接在一起链表)
但是索引也需要占用空间,创建维护索引需要时间,在数据量很小的情况下,使用索引不占优势(比如2行数据…)
一般大型表才会使用索引,但是超大型表建立索引也非常麻烦,可以分表
不会作为where条件出现的字段不需要建立索引;某个字段增删改多,查少,就不需要索引
多个字段经常联合查找使用联合索引,字段多且不重复可以使用唯一索引,有重复就是用普通索引(唯一索引查找更快)
索引数据结构? Hash和B+区别?
索引的数据结构主要就是Hash和B+,InnoDB索引类型有Hash索引和B+索引,默认采用B+索引
Hash索引基于Hash表实现,对于每一行数据,通过hash算法计算hash code,这样查询每一行数据的时间复杂度就是O(1), 一般用于精确查找(并且会遇到hash冲突)
B+树、AVL树、红黑树典型数据结构
B+树中,所有的记录数据结构都是按照key值大小的顺序放在叶子节点,B+树具有有序性
B+树的索引分为主索引和辅助索引,主索引为聚簇索引,辅助索引为非聚簇索引(聚簇主键构建B+,非聚簇采用非主键)
B树所有节点都会存储key和数据,B+树只有叶子节点存放data,B树相当于范围内每一个节点做二分,B+都是根找到叶子,叶子顺序(顺序IO)
Hash索引一般用于精确查找,不支持排序(hash表无序)、不支持范围查找、不支持模糊查询和最左前缀匹配,并且性能不稳定
除了极少部分精确查找可以使用hash,其余都可以使用B+,支持排序、支持范围、支持模糊、最左匹配…
B和B+区别,为什么使用B+?
B和B+主要区别:
- B Tree中所有节点都会存储key和data,而B+ Tree中非叶节点只存储key,叶子节点会存储key和data
- B+ 树所有的叶子节点是连接在一起的(链表),方便顺序IO,所有key都会在叶子出现一次(包括内节点的)
B树适合随机检索,B+树适合随机和顺序检索,B+树的空间利用率高(因为非叶节点不存储data,可以存储更多所有,树高度降低,IO次数减少)
B+树的所有叶子链接在一起,适合范围查找、顺序查找,性能稳定(因为一定在叶子找到,而B树可能在内部找到)
聚簇索引和非聚簇索引?
聚簇和非聚簇的区别就是数据和索引是否分开存储;
MyISAM中都是非聚簇索引,InnoDB一张表最多一个聚簇索引,一般情况下就是主键索引,其他的索引比如普通索引和联合索引就是辅助索引
聚簇索引: 数据和索引放在一起存储,索引结构的叶子节点包含数据行 InnoDB
非聚簇索引: 数据和索引分开存储,MyISAM,索引叶子系欸但存储的是指向数据行的地址
InnoDB中,默认索引结构为B+树索引,利用主键创建的索引为主索引(聚簇索引),在主索引上创建的索引为辅助索引(非聚簇索引),辅助索引的叶节点存储的是主键
MyISAM中,默认的结构也是B+,但是主索引和辅助索引都是非聚簇索引,索引结构的叶子节点存储的都是地址,而不是具体的data【InnoDB的主索引叶子节点存储的就是具体的data】
查询操作时依靠查询字段,按照非聚簇索引(辅助索引)查找到数据记录,再通过主键key查找到具体的元组,也就先普通索引查找,再回表查询
非聚簇索引一定会回表查询?
非聚簇索引叶子节点存储的是主键,查找时先通过辅助索引找到主键,再通过主索引获取对于的元组数据, 通过聚簇索引找到主键对于数据的过程就是回表查询
不一定每次查询都要回表,索引覆盖时,就不用
比如 SELECT id, name where name = ‘ZS’; name为普通索引,id主键索引,name非聚簇索引就可以查找到name和id; 不需要再回表查询其他的字段,但是select id,name,age where name = ‘ZS’ 需要回表查询,因为name的索引不能找到age值
索引类型(结构)?
索引的类型包括FULLTEXT、HASH(等值查询)、BTREE(B+,默认)、RTREE(空间数据索引,地理数据存储、范围查找)
- 全文索引: FULLTEXT,MyISAM和mysql5版本以上的InnoDB都支持全文索引,主要就是TEXT、CHAR等类型字段上创建全文索引
- HASH: 等值查询,不支持排序模糊、范围、性能不稳定
- BTREE: B+树结构,支持排序…
- RTREE: 空间数据索引,常用于地理数据的存储,优势在于范围查找
索引种类
普通索引: 基本类型
唯一索引: 唯一性约束 (会自动)
主键索引: 一个表一个,主键上 (会自动)
组合索引: 多个字段上
全文索引: 文本内容搜索、MyISAM和高版InnoDB支持,TEXT等字符串类型字段上
索引覆盖
索引覆盖针对的是Select后的字段,当select后的字段都有索引时,就算没有where条件或者where条件后没有索引项,也会自动走索引
所以不推荐直接select * , 因为正常情况下* 一定包含没有索引字段,不会索引覆盖
什么是前缀索引,最左匹配原则?
前缀索引针对的是字符串类型的字段,字符串类型字段可以建立前缀索引,也就是只是对字符串的前几个字符建立索引,这样索引更短,IO更少,性能更好
ALTER TABLE table_name ADD KEY(col_name(prefix_len)); prefix_len
最左匹配原则:(因为索引是字典类似)从最左边为起点连续匹配,遇到范围查询< > between会停止
其实就是按照字典习惯,从最左边的字符开始进行匹配,匹配上继续匹配第二个…
比如联合索引idx_a_b_c 最左匹配就是从a开始匹配,如果没有a就匹配不上
select * from t where a = xxx; 👌
select * from t where b = xx and a = xx and c = xx 这里sql的优化器会自动调整顺序,所以where后面的顺序无影响
如果没有a,只有b、c是匹配不上的,a、c可以匹配,只要包含a就可以匹配
索引设计原则
最适合建立索引的是频率较高的where条件字段,不是select后面的
索引列基数越大效果越好,比如性别就不适合建立索引,取值基数小
尽量使用短索引,磁盘IO少
尽量利用最左前缀
不要过度使用索引,索引需要额外的物理空间存储,创建维护需要时间
索引失效的情况?
- OR 连接的某个字段没有索引 【全有索引才走索引】
- 索引字段上有运算、函数 【比如age + 1, TOUPPERCASE(name)】
- 模糊查询like以%开头 【匹配不上,索引B+树中找不到】
- 使用了范围查询< , > 【找不到具体节点,可以使用<=】
- 使用了!= 、 not(not in、not null、not exists…)
- 联合索引不满足最左匹配原则
- 类型不一致 【字符串类型字段传入int类型(mysql只能隐式将string转为int】
- 索引对比 【两个建立索引的字段作为条件 a = b,不知道走那个索引】
- 字符集不一致
索引优化?
索引优化就是将不符合索引设计原则和使用场景的索引优化为符合设计原则的索引:
少使用Select * (索引覆盖)、 区分度高的索引放在前面、避免索引失效
数据库事务
事务就是逻辑上的一组一体化的操作,要么都完成,要么都失败,最经典的就是转账
数据库四大特性:
ACID:
automic: 原子性,一体化,要么全部指向成功,要么全部失败
consistency: 一致性:要保证事务指向前后的数据一致性
isolution: 隔离性,一个事务执行时对其他事务不可见
duration: 持久性,数据提交之后,修改应该永久保存
数据库并发一致性问题:
丢失修改:…; 脏读 ; 不可重复读, 幻影读
【不可重复读着重强调数据前后读取不一致,也就是被update了; 而幻影读则是强调有新的数据插入或者数据删除insert和delete】
数据库隔离级别:
READ UNCOMMIT: 未提交读,可以读取未提交的数据,解决丢失修改(修改前加X锁),会出现 脏读、幻读、不可重复读
READ COMMITED: 已提交读: 只能读取已经提交的数据(在前面的基础上,读取数据前尝试加S锁,读完释放) ,解决脏读
REPEATEABLE READ : 可重复读, 多次读取的数据是一致的(在前面的基础上,读取数据前加S锁,事务结束才释放),解决可重复读,MySQL的隔离界别不仅仅基于锁,还有MVCC,所以也可以解决幻影读
SERIALIZABLE: 串行化, 类似单线程模式,事务串行执行,解决了所有并发一致性问题
MySQL隔离级别是基于数据库锁实现?MVCC
MySQL的隔离级别基于锁和MVCC机制共同实现的,SERIABLZABLE隔离级别基于锁实现,其余的都是基于MVCC实现,REPEATABLE-READ是基于锁和MVCC(多版本并发控制)共同实现
默认隔离级别可重复读
当前读和快照读?
快照读是不加锁读取,当前都是加锁读取
快照读(一致性非锁定读): 就是SELECT 语句,不包括加锁语句
SELECT.... FRO UPDATE ; 悲观锁,行级锁,X锁
SELECT ..... LOCK IN SHARE MODE ; 共享锁,S锁
快照也就是记录的历史版本,每行记录可能多个历史版本(MVCC的undo日志); 快照读也就是不加锁的读, 所以更快【一致性要求低】
如果遇到正在修改的记录(X锁),不会等待,而是记录快照
RC读已提交: 快照数据,读取锁定行的最新快照
RR可重复读: 快照数据,读取锁定行锁定前的快照
当前读:一致性锁定读: 会给行记录加X锁或者S锁; 带锁读取
一致性好,因此速度较快照读慢
SELECT ... FRO UPDATE
SELECT ... LOCK IN SHARE MODE
加上X锁
INSERT
UPDATE
DELETE
什么是MVCC?
MVCC主要就是记录的行,通过回滚指针进行回滚,就是一个类似行级锁,便于进行快照读
多版本并发控制multi version concurrent control, 是控制并发的一种方法,可以提高并发性能
MVCC的作用就是在不加锁的情况下解决读写冲突问题,不能解决丢失修改,但是可重复读可以解决
MVCC实现:
- 版本号:包括系统版本号:自增的代表事务的ID; 事务版本号:事务开始时的系统版本号,可以判断时间
- 行记录隐藏列: DB_ROW_ID: 6Byte,用于生成聚簇索引;DB_TRX_ID:6Byte,最近修改的事务ID — 最近操作这条记录的版本号; DB_ROLL_PTR:7byte,回滚指针,指向上一个版本号
- undo日志: MVCC使用的快照会存在undo日志,DB_ROLL_PTR回滚指针会将一个一个数据行连接起来,也就是当前行的所有的历史操作记录,便于回滚
MVCC的作用就是在避免直接加锁的情况下,最大限度解决并发问题,可以可重复读
数据库 锁
数据库有并发事务的时候,保证数据访问安全和顺序的机制就是锁机制
数据库隔离级别和数据库锁的关系?
按照Cfeng的理解:【网上答案层次不齐】
- 读未提交: 对应的是数据库的一级封锁协议,修改数据前加锁X锁,事务结束释放
- 读已提交: 对应 二级封锁协议, 在一级协议基础上,读取数据时尝试加S锁,读取结束立刻释放 SELECT … LOCK IN SHARE MODE
- 可重复读: 对应 三级封锁协议, 在二级协议的基础上,读取数据时尝试加S锁,事务结束后才释放
- 串行化: 类似事务开始前加锁排他锁,知道事务结束才释放
数据库锁的类型?
按照锁的粒度:
- 表级锁: 资源开销小,加锁速度快,不会死锁,MyISAM和InnoDB都支持,操作时锁整张表,并发度低
- 行级锁: 资源开销大,加锁速度快,因为粒度更小,资源更多,所以容易死锁,并发度高; MyISAM不支持
按照锁的类别:
- 共享锁: S锁,只能读取,其他事务可以再加S锁,但是不能加X锁
- 排他锁: X锁,只能当前事务读取修改,其他事务不能加任何锁
因为MySQL使用了MVCC,所以普通的SELECT 语句不会显示加锁的,但是也是可以通过for update或者lock in share mode显示加X或者S锁
什么是乐观锁、悲观锁?
乐观锁和悲观锁是programmer对于锁的一个感性描述
乐观锁: 乐观认为读多写少,所以数据库只是在数据更新时检查,如果冲突,更新失败,一般通过version版本号或者CAS实现【无锁结构】
悲观锁:悲观认为写多读少,所以需要加锁,使用数据库锁机制,也就是行锁for update
什么时意向锁?
当需要使用表锁,需要判断是否有行锁,就可以使用意向锁【粒度不同】
意向锁是表级锁,包括IS锁,IX锁:
意向共享锁: Intention Shared Lock: 事务有意向对表中某些数据加S锁,需要先对表加IS锁
意向排他锁: Intention Exclusion Lock: 事务对表中数据加X锁,需要先对表加IX锁
意向锁是数据引擎操作,用户不能手动操作,在加S、X锁前,InnoDB会先获取IS/IX锁
意向锁不会与行级锁冲突,是兼容的
InnnoDB行级锁类别?
记录锁: Record Lock: 单个行记录上的锁,对索引项加锁
间隙锁: Gap Lock: 锁定一个范围(索引之间间隙、第一条记录前的间隙、最后一条后的间隙 — 防插入),不包括记录本身
临键锁: Next-Key Lock: 锁定一个范围,包括记录本身,是记录锁和间隙锁的组合 【记录锁锁住已经存在记录,避免新记录需要间隙锁】
MVCC不能解决幻读问题,Mysql可重复读级别依靠MVCC + Next-Key Lock解决幻读
; 临键锁是记录锁和间隙锁的结合,可以锁住记录范围,避免新纪录插入
InnoDB行级锁使用注意?
InnoDB的行锁时针对索引字段加的锁,表级锁针对非索引字段,当进行更新删除操作时,如果WHERE条件中字段没有命中唯一索引或者索引失效,那么会锁住所有行,变为表锁!
InnoDB不通过索引字段查询或者索引失效,那么InnoDB使用就不是行锁,而是表锁!
死锁? MySQL如何避免?
死锁就是两个或者两个以上进程,由于竞争资源或者彼此同学造成的阻塞现象【操作系统、语言中都有】,MyISAM只有表锁,一次获取所有的资源,不满足环路等待,不会死锁
InnoDB加锁的粒度为行,除了单个SQL记录,锁都是逐步获取的(不同行),存在死锁问题 (互斥、请求保持,不可剥夺,环路等待)
避免方式:
- 并发存取时,获取资源的顺序尽量一致, 这样就不会请求保持
- 一次性获取所有资源,如果并发要求不高,可以表锁
- 使用较低隔离级别 【破环不可剥夺】
- 使用索引访问数据,这样行级锁,减少锁冲突
- 合理选择事务,查询操作尽量不显式加锁(MVCC即可)
…
数据库优化
SQL执行很慢原因?
- 如果SQL是偶尔执行很慢,可能执行时遇到了锁,或者redo log写满,需要进行日志写入磁盘操作
- 如果一直都很慢,可能是字段没有索引或者索引失效
慢查询? 如何优化?
慢查询用于记录执行时间超过阈值的SQL语句
slow_query_log: 是否开启慢查询日志 …
优化慢查询:
- 分析语句的执行计划,查看SQL语句索引是否命中(是否失效)
- 优化数据库结构,分库分表
- 优化LIMIT分页
查询过程数据访问如何优化?
减少数据访问层面: 使用索引,索引覆盖,优化SQL
返回数据更少层面: 数据分页、只返回需要的字段
从CPU开销层面: 合理使用排序,减少比较操作,复杂的运算在应用层解决
从效率层面: 多进程并发访问,数据库并行处理;数据库集群
长难查询语句如何优化?
将一个大的查询分解为多个小的查询
分解关联查询,核心就是分解
如何优化LIMIT分页?
Limit分页start越大,查询时间越长,因此:
可以记录每次取出数据的最后一行的ID,下一次利用ID先过滤
或者可以建立联合索引,加速访问
如何优化UNION?
如果不需要排序、去重,使用union all性能更快
如何优化where?
一般使用索引的时候,那就要避免索引失效,所以不要使用Not(null,in,exists),不要使用范围条件(< > between), 保证联合查询符合最左匹配原则,字符串类型字段需要加引号,避免量个索引项字段直接比较
使用OR需要慎重,可以使用union all代替or
不要在索引项使用函数或者运算
总之就是要避免索引失效从而进行全表扫描(亿级数据太耗时)
大表数据查询如何优化?
- 索引优化: 满足索引的原则,避免索引失效
- SQL语句优化: mysql优化器有局限,手动优化,explain慢查询分析
- 分表 ------ 水平拆分、垂直拆分
- 建立中间表
- 使用Cache
- 固定表的长度,访问较短的索引列
- 主从复制,主写从读,读写分离
- 避免无任何限制的查询( 水平限制,分页)
mysql的微服务级别的分库分表myCat和填充亿级数据等内容Cfeng放在下次分享,本文给出答案很简洁,如有不懂,请查阅相关资料🎄