为什么要优化
系统的吞吐量瓶颈往往出现在数据库的访问速度上
如何优化
- SQL语句的优化(收效甚微)
- 设计数据库时:数据库表、字段的设计,存储引擎
- 利用好MySQL自身提供的功能,如索引等
- 横向扩展:MySQL集群、负载均衡、读写分离
SQL语句的优化
select * 要少用
应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
尽可能使用 not null
in 和 not in 也要慎用,否则会导致全表扫描
设计数据库表时尽量满足三范式(3NF)
一范式:字段原子性,字段不可再分割。
二范式:消除对主键的部分依赖 ;即在表中加上一个与业务逻辑无关的字段作为主键
三范式:消除对主键的传递依赖;方便理解,可以看做是“消除冗余”。 每个属性都跟主键有直接关系而不是间接关系。像:a-->b-->c 属性之间含有这样的关系,是不符合第三范式的。
存储引擎选择
现在不存在这个问题了,Innodb不断完善,从各个方面赶超MyISAM,也是MySQL默认使用的。
锁扩展
表级锁(table-level lock
):lock tables <table_name1>,<table_name2>... read/write
,unlock tables <table_name1>,<table_name2>...
。其中read
是共享锁,一旦锁定任何客户端都不可读;write
是独占/写锁,只有加锁的客户端可读可写,其他客户端既不可读也不可写。锁定的是一张表或几张表。
行级锁(row-level lock
):锁定的是一行或几行记录。共享锁:select * from <table_name> where <条件> LOCK IN SHARE MODE;
,对查询的记录增加共享锁;select * from <table_name> where <条件> FOR UPDATE;
,对查询的记录增加排他锁。这里值得注意的是:innodb
的行锁,其实是一个子范围锁,依据条件锁定部分范围,而不是就映射到具体的行上,因此还有一个学名:间隙锁。比如select * from stu where id < 20 LOCK IN SHARE MODE
会锁定id
在20
左右以下的范围,你可能无法插入id
为18
或22
的一条新纪录。
索引
index索引
我以为我对Mysql索引很了解,直到我遇到了阿里的面试官
分表
1)水平划分
如果某个表的数据太多,预期有上千条甚至上亿以上,我们可以化整为0:拆表。
这里就涉及到拆表的算法:
记录日志的表,也可以按周或者按月来拆。
记录用户信息的表,按用户id的hash算法来拆。
2)垂直拆分
如果表记录数并不多,可能也就2、3万条,但是字段却很长,表占用空间很大,检索表时需要 执行大量I/O,严重降低了性能。这个时候需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。
主从复制 读写分离
读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
网友评论