MySQL优化常用方法

1、数据库表结构设计

首先从业务出发,可利用ER图理清实体及实体之间的关系,包括一对一,一对多,多对多关系,多对多关系需要中间表。实体间的关系应该通过实体表的主键进行关联,不要使用非主键进行关联,以免留下后患。

 

其次,在设计数据库时,可先遵循范式进行设计,一般违反范式进行设计,也能带来好处,但会引入冗余。冗余利于数据查询,提升查询性能,但会造成数据不一致,因此需要维护冗余字段。

 

可在表中引入四个字段,创建人、更新人、创建时间、更新时间,这样非常便于排查测试、生产环境问题。

 

2、数据库字段设计 

首先是命名规范,使用英文,多个单词以下划线隔开。其次尽量使用可以存储数据的最小数据类型。整型比字符操作代价更低,因为字符集和排序规则使字符比整型比较更复杂;使用时间类型而不是字符串类型类存储日期和时间;如果计划在列上建索引,应避免将该列默认值设为null;使用Decimal存储比Bigint更大的整数,建议只指定数据类型,不指定精度。Varchar类型存储可边长字符串,需要1或2个额外字节记录字符串的长度,如果列的最大长度小于或等于255字节,则只使用1个字节表示,否则使用2个字节,故最多能存储65535个字符。

 

3、MySQL常用SQL查询语句优化方法

⑴、应尽量避免在where子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。

⑵、对查询进行优化,应尽量避免全表扫描,首先考虑在where及order by涉及的列上建立索引。

⑶、应尽量避免在where子句中字段进行null值判断,否则引擎将放弃使用索引而进行全表扫描。

⑷、OR前后两个条件都要有索引整个SQL才会使用索引,只要有一个条件没索引整个SQL就不适用索引。

⑸、MySQL将IN()列表中的数据先进行排序,然后通过二分查找的方式来确定列表中的值是否满足条件,这是一个O(log n)复杂度的操作,等价地转换成OR查询的复杂度为O(n),对于IN()列表中大量取值的时候,MySQL的处理速度将会更快。

⑹、左模糊查询将导致全表扫描。

⑺、不要在where子句中对字段进行函数、表达式操作,这样将导致全表扫描。

⑻、在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,应尽可能的让字段顺序与索引顺序一致。

⑼、避免隐式类型转换,如字符串应加单引号,否则会导致全部扫描。

⑽、任何地方都不要使用select * from t,用具体的字段列表代替“*”,不要返回用不到的任何字段,这样会导致回表。

⑾、尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

⑿、尽量避免大事务操作,提高系统并发能力。

 

4、SQL调优方式

MySQL调优的时候会用到explain来看select语句的执行情况。Explain语句中的type列和extra列反映了访问类型。type列访问类型有很多种,从全表扫描(All)到索引扫描(index)、范围扫描(range)、唯一索引查询(ref)、常数引用(const)等。速度从慢到快、扫描的行数从大到小。

⑴、All:mysql从头到尾遍历整个表,找到所需要的数据行。

⑵、index:仅仅局限在扫描全表的顺序是按照索引顺序扫描的,因为索引是有序的,故可避免排序,但承担了按照索引顺序扫描整张表的开销。例如查询中有order by id,id是这个表的索引,但是因为没有在where中出现任何的索引列,所以它只是按索引顺序扫描了全表。

⑶、range:一般在where语句中出现between或者“>”这种符号的时候会出现这个。这种范围扫描索引比全表扫描要好,因为它只需开始于索引的某一点,结束于另一点,不用扫描全部索引。

⑷、ref:它返回所有匹配某个单独值的行,然而它可能找到多个符合条件的行。属于查找和扫描的混合体。

⑸、const:当mysql能对查询的部分进行优化,并且转换成一个常量的时候,它就会使用这种访问类型。如把一行的主键当作where条件,mysql可以把它转换成一个常量,然后查询。

Etra列中出现的信息一般不是太重要,但是也有很多信息可以获取到

⑴、using index:说明mysql使用了覆盖索引,避免访问了表的数行和回表,效率高。

⑵、using where:在查找使用索引的情况下,需要回表去查询所需的数据。

⑶、using temporary:mysql对查询结果进行排序的时候使用了一张临时表。

⑷、using filesort:mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。

 

5、B-tree、B+tree和索引类型

B-tree是一种多路自平衡搜索树,它类似普通的二叉树,但是B-tree允许每个节点有更多的子节点,B-tree示意图如下:

                     MySQL优化常用方法_第1张图片

B-tree的特点:

⑴、所有键值分布在整个树中

⑵、任何关键字出现且只出现在一个节点中

⑶、搜索有可能在非叶子节点结束

⑷、在关键字全集内做一次查找,性能逼近二分查找算法

 

B+tree是B-tree的变体,也是一种多路平衡查找树,B+树的示意图为:

                    MySQL优化常用方法_第2张图片

从图中可以看出,B+树与B树的不同在于:

⑴、所有关键字存储在叶子节点,非叶子节点不存储真正的data

(2)、所有叶子节点增加了一个链指针

聚簇索引:即为主键索引,InnoDB通过主键聚集数据,如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。

非聚簇索引:即为非主键索引。

覆盖索引:通过索引查询数据,不需要回表的索引,主键索引也为覆盖索引。

 

6、Mysql查询执行的过程

⑴、客户端发送一条查询给服务器

⑵、服务器先检查查询缓存,如果命中了缓存,则立刻返回存储再缓存中的结果。否则进入下一阶段。

⑶、MySql解析器通过关键字将SQL语句进行解析,生成一颗解析树。MySQL解析器将使用MySQL语法规则验证和解析查询。

⑷、预处理器根据MySQL规则进一步检查解析树是否合法,这里将检查数据表和数据列是否存在,还会解析名字和别名,看看它们是否有歧义。

⑸、到查询优化器,此时语法树是合法的了,查询优化器将其转化为执行计划,调用存储引擎API来执行查询。一条查询可以有很多种执行方式,最后都返回相同的结果。

⑹、将结果返回给客户端。

 

7、一、二、三范式的直白解释

第一范式:数据表中的列应为独立的列,一个列不应存储多列的值

第二范式:数据表中不存在部分函数依赖,即当表中有联合索引时,非主键列应完全依赖该联合索引中的所有列,而不是只依赖其中的部分列。

第三范式:数据表中不存在传递函数依赖,即非主键列完全依赖主键列,而不是,非主键列依赖于该表中的其他非主键列。

 

8、事物及其隔离级别直白解释

事务就是一组原子性的SQL语句组成的工作单元。所谓原子性就是最小的,不可在分隔的。

事务的ACID属性:

⑴、原子性:一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。

⑵、一致性:数据库总是从一个一致性的状态转换到另外一个一致性的状态。

⑶、隔离性:一个事务所做的修改在最终提交以前,对其他事务时不可见的。

⑷、持久性:一旦事务提交,则其所做的修改就会永久保存到数据库中。

事务的隔离级别:

⑴、未提交读:事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取其他事务未提交的数据,造成脏读。这个级别会导致很多问题,很少使用。

⑵、提交读:大多数数据库系统默认的隔离级别都是提交读(但MySQL不是)。一个事物从开始直到提交之前,所做的任何修改对其他事物都是不可见的,但是提交之后,对其他事物就是可见的,因此,另一个事务在未提交之前,两次执行同样的查询,可能会得到不一样的结果,从而造成不可重复读。

⑶、可重复读:该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但会存在幻读的问题。可重复读是MySQL的默认事务隔离级别。

⑷、可串行化:是最高的隔离级别。它通过强制事务串行执行,避免幻读问题。

 

9、不可重复读与幻读的区别

它们的关注点是在同一个事务中,两次相同查询的结果不同。不可重复读重点是同一条数据的值不一样,侧重修改。幻读是两次相同查询的结果条数不同,侧重的是记录数,innodb通过引入版本号列的并发控制,解决了幻读的问题。

 

10、锁和并发控制

       在处理并发读或者写时,可以通过实现一个由两种类型的锁组成的锁系统来解决问题。这两种类型的锁通常被称为共享锁和排他锁,也叫读锁和写锁。读锁是共享的,或者说是相互不阻塞的。写锁则是排他的,也就是说一个写锁会阻塞其他的写锁或读锁,这是处于安全策略的考虑,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。

       悲观锁包括共享锁和排他锁。读锁不阻塞读锁,但阻塞写锁;写锁阻塞读写锁。乐观锁并不是真正的锁机制,而是一种逻辑锁,通过版本号来使数据最终一致性。

       锁定的数据量越少,则系统的并发程度越高,只要相互之间不发生冲突即可。写锁比读锁有更高的优先级,因此一个写锁请求可能会被插入到读锁队列的前面。

你可能感兴趣的:(MySQL,MySQL)