共计 4035 个字符,预计需要花费 11 分钟才能阅读完成。
前言
本文次要针对的是关系型数据数据库 MySql。键值类数据库能够参考:
https://www.jianshu.com/p/098a870d83e4
先简略梳理下 Mysql 的基本概念,而后分创立时和查问时这两个阶段的优化开展。
1 基本概念简述
1.1 逻辑架构
- 第一层:客户端通过连贯服务,将要执行的 sql 指令传输过去
- 第二层:服务器解析并优化 sql,生成最终的执行打算并执行
- 第三层:存储引擎,负责数据的贮存和提取
1.2 锁
数据库通过锁机制来解决并发场景 - 共享锁(读锁)和排他锁(写锁)。读锁是不阻塞的,多个客户端能够在同一时刻读取同一个资源。写锁是排他的,并且会阻塞其余的读锁和写锁。简略提下乐观锁和乐观锁。
- 乐观锁,通常用于数据竞争不强烈的场景,多读少写,通过版本号和工夫戳实现。
- 乐观锁,通常用于数据竞争强烈的场景,每次操作都会锁定数据。
要锁定数据须要肯定的锁策略来配合。
- 表锁,锁定整张表,开销最小,然而会加剧锁竞争。
- 行锁,锁定行级别,开销最大,然而能够最大水平的反对并发。
然而 MySql 的存储引擎的实在实现不是简略的行级锁,个别都是实现了多版本并发管制(MVCC)。MVCC 是行级锁的变种,少数状况下防止了加锁操作,开销更低。MVCC 是通过保留数据的某个工夫点快照实现的。
1.3 事务
事务保障一组原子性的操作,要么全副胜利,要么全副失败。一旦失败,回滚之前的所有操作。MySql 采纳主动提交,如果不是显式的开启一个事务,则每个查问都作为一个事务。
隔离级别管制了一个事务中的批改,哪些在事务内和事务间是可见的。四种常见的隔离级别:
- 未提交读(Read UnCommitted),事务中的批改,即便没提交对其余事务也是可见的。事务可能读取未提交的数据,造成脏读。
- 提交读(Read Committed),一个事务开始时,只能看见已提交的事务所做的批改。事务未提交之前,所做的批改对其余事务是不可见的。也叫不可反复读,同一个事务屡次读取同样记录可能不同。
- 可反复读(RepeatTable Read),同一个事务中屡次读取同样的记录后果时后果雷同。
- 可串行化(Serializable),最高隔离级别,强制事务串行执行。
1.4 存储引擎
InnoDB 引擎,最重要,应用最宽泛的存储引擎。被用来设计解决大量短期事务,具备高性能和主动解体复原的个性。
MyISAM 引擎,不反对事务和行级锁,解体后无奈平安复原。
2 创立时优化
2.1 Schema 和数据类型优化
整数
TinyInt,SmallInt,MediumInt,Int,BigInt 应用的存储 8,16,24,32,64 位存储空间。应用 Unsigned 示意不容许正数,能够使负数的上线进步一倍。
实数
- Float,Double , 反对近似的浮点运算。
- Decimal,用于存储准确的小数。
字符串
- VarChar,存储变长的字符串。须要 1 或 2 个额定的字节记录字符串的长度。
- Char,定长,适宜存储固定长度的字符串,如 MD5 值。
- Blob,Text 为了存储很大的数据而设计的。别离采纳二进制和字符的形式。
工夫类型
- DateTime,保留大范畴的值,占 8 个字节。
- TimeStamp,举荐,与 UNIX 工夫戳雷同,占 4 个字节。
优化倡议点
- 尽量应用对应的数据类型。比方,不要用字符串类型保留工夫,用整型保留 IP。
- 抉择更小的数据类型。能用 TinyInt 不必 Int。
- 标识列(identifier column),倡议应用整型,不举荐字符串类型,占用更多空间,而且计算速度比整型慢。
- 不举荐 ORM 零碎主动生成的 Schema,通常具备不重视数据类型,应用很大的 VarChar 类型,索引利用不合理等问题。
- 实在场景混用范式和反范式。冗余高查问效率高,插入更新效率低;冗余低插入更新效率高,查问效率低。
- 创立齐全的独立的汇总表 \ 缓存表,定时生成数据,用于用户耗时工夫长的操作。对于精确度要求高的汇总操作,能够采纳 历史后果 + 最新记录的后果 来达到疾速查问的目标。
- 数据迁徙,表降级的过程中能够应用影子表的形式,通过批改原表的表名,达到保留历史数据,同时不影响新表应用的目标。
2.2 索引
索引蕴含一个或多个列的值。MySql 只能高效的利用索引的最左前缀列。索引的劣势:
- 缩小查问扫描的数据量
- 防止排序和零时表
- 将随机 IO 变为程序 IO(程序 IO 的效率高于随机 IO)
B-Tree
应用最多的索引类型。采纳 B -Tree 数据结构来存储数据(每个叶子节点都蕴含指向下一个叶子节点的指针,从而不便叶子节点的遍历)。B-Tree 索引实用于全键值,键值范畴,键前缀查找,反对排序。
B-Tree 索引限度:
- 如果不是依照索引的最左列开始查问,则无奈应用索引。
- 不能跳过索引中的列。如果应用第一列和第三列索引,则只能应用第一列索引。
- 如果查问中有个范畴查问,则其左边的所有列都无奈应用索引优化查问。
哈希索引
只有准确匹配索引的所有列,查问才无效。存储引擎会对所有的索引列计算一个哈希码,哈希索引将所有的哈希码存储在索引中,并保留指向每个数据行的指针。
哈希索引限度:
- 无奈用于排序
- 不反对局部匹配
- 只反对等值查问如 =,IN(),不反对 < >
优化倡议点
- 留神每种索引的适用范围和实用限度。
- 索引的列如果是表达式的一部分或者是函数的参数,则生效。
- 针对特地长的字符串,能够应用前缀索引,依据索引的选择性抉择适合的前缀长度。
- 应用多列索引的时候,能够通过 AND 和 OR 语法连贯。
- 反复索引没必要,如(A,B)和(A)反复。
- 索引在 where 条件查问和 group by 语法查问的时候特地无效。
- 将范畴查问放在条件查问的最初,避免范畴查问导致的左边索引生效的问题。
- 索引最好不要抉择过长的字符串,而且索引列也不宜为 null。
3 查问时优化
3.1 查问品质的三个重要指标
- 响应工夫(服务工夫,排队工夫)
- 扫描的行
- 返回的行
3.2 查问优化点
- 防止查问无关的列,如应用 Select * 返回所有的列。
- 防止查问无关的行
- 切分查问。将一个对服务器压力较大的工作,合成到一个较长的工夫中,并分屡次执行。如要删除一万条数据,能够分 10 次执行,每次执行实现后暂停一段时间,再继续执行。过程中能够开释服务器资源给其余工作。
- 合成关联查问。将多表关联查问的一次查问,分解成对单表的屡次查问。能够缩小锁竞争,查问自身的查问效率也比拟高。因为 MySql 的连贯和断开都是轻量级的操作,不会因为查问拆分为屡次,造成效率问题。
- 留神 count 的操作只能统计不为 null 的列,所以统计总的行数应用 count(*)。
- group by 依照标识列分组效率高,分组后果不宜出行分组列之外的列。
- 关联查问提早关联,能够依据查问条件先放大各自要查问的范畴,再关联。
-
Limit 分页优化。能够依据索引笼罩扫描,再依据索引列关联本身查问其余列。如
SELECT id, NAME, age WHERE student s1 INNER JOIN ( SELECT id FROM student ORDER BY age LIMIT 50,5 ) AS s2 ON s1.id = s2.id
- Union 查问默认去重,如果不是业务必须,倡议应用效率更高的 Union All
补充内容
来自大神 - 小宝
1. 条件中的字段类型和表构造类型不统一,mysql 会主动加转换函数,导致索引作为函数中的参数生效。
2.like 查问后面局部未输出,以 % 结尾无奈命中索引。
3. 补充 2 个 5.7 版本的新个性:
generated column,就是数据库中这一列由其余列计算而得
CREATE TABLE triangle (sidea DOUBLE, sideb DOUBLE, area DOUBLE AS (sidea * sideb / 2));
insert into triangle(sidea, sideb) values(3, 4);
select * from triangle;
+-------+-------+------+
| sidea | sideb | area |
+-------+-------+------+
| 3 | 4 | 6 |
+-------+-------+------+
反对 JSON 格局数据,并提供相干内置函数
CREATE TABLE json_test (name JSON);
INSERT INTO json_test VALUES('{"name1":"value1","name2":"value2"}');
SELECT * FROM json_test WHERE JSON_CONTAINS(name, '$.name1');
来自 JVM 专家 - 达
关注 explain 在性能剖析中的应用
EXPLAIN SELECT settleId FROM Settle WHERE settleId = "3679"
- select_type,有几种值:simple(示意简略的 select,没有 union 和子查问),primary(有子查问,最里面的 select 查问就是 primary),union(union 中的第二个或随后的 select 查问,不依赖内部查问后果),dependent union(union 中的第二个或随后的 select 查问,依赖内部查问后果)
- type,有几种值:system(表仅有一行(= 零碎表),这是 const 连贯类型的一个特例),const(常量查问), ref(非惟一索引拜访,只有一般索引),eq_ref(应用惟一索引或组件查问),all(全表查问),index(依据索引查问全表),range(范畴查问)
- possible_keys: 表中可能帮忙查问的索引
- key,抉择应用的索引
- key_len,应用的索引长度
- rows,扫描的行数,越大越不好
- extra,有几种值:Only index(信息从索引中检索出,比扫描表快),where used(应用 where 限度),Using filesort(可能在内存或磁盘排序),Using temporary(对查问后果排序时应用长期表)
逆锋起笔
是一个专一于程序员的编程圈子,以分享java
、Python
、学习资源
为主,关注即可支付 23 种精选的编程视频教程和大佬们举荐的电子版学习材料!