不删库不跑路 -- 数据库优化

Posted 小强的进阶之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不删库不跑路 -- 数据库优化相关的知识,希望对你有一定的参考价值。


数据库mysql在后端开发工作中,必不可少,关于mysql优化的知识也是后端工程师必备的。接下来小强将分阶段的向大家介绍关于关于Mysql优化的相关知识。

不删库不跑路 -- 数据库优化
一、优化概述
不删库不跑路 -- 数据库优化

以下是从官方文档摘抄出来的关于Mysql优化的概述

Optimization Overview:Database performance depends on several factors at the database level, such as tables, queries, and configuration settings.

由此可见,数据库的性能是由多方面因素影响的,包括硬件设备、数据库表设计、查询语句、数据库配置等等。

1.1数据库层面:表格设计,查询语句,配置信息等

关于这方面的考虑,我们需要问自己这样几个问题:

  •     数据库是否设计合理?

  •     每列是否有正确的数据类型,每列的长度是否合理? 我们要注意的是经常update的表要少些列,否则性能会变差。

注意InnoDB的一些基本特性如下:

每个InnoDB存储引擎的表,最大为1000个列,一行数据的大小小于二分之一页的大小(默认一页16KB),即8000个字节。但是不包括VARBINARY、VARCHAR、BLOB、or TEXT类型.

  •     index设计合理?

  •    是否选择了正确的存储引擎?InnoDb 还是 MyISAM?(Mysql5.5以上默认都是InnoDB)

    不删库不跑路 -- 数据库优化

  •   我们的应用是否使用了正确的锁机制?大量请求并行?

    从InnoDB官方文档中,我们可以看到InnoDB本身解决了很多关于锁的问题

The InnoDB storage engine handles most locking issues without involvement from you, allowing for better concurrency in the database and reducing the amount of experimentation and tuning for your code.

  •    合适的缓存大小?

以上的这些问题,在接下来的篇章中都会一一介绍。

1.2硬件层面

硬件层面的优化我们考虑的问题主要有以下几点:


  • 硬盘查找、平均查找时间小于10ms

  • 分布式解决

  • 读写分离

  • CPU 内存带宽(memory bandwidth)

1.3 MyISAM & InnoDB差别

两个搜索引擎主要区别如下:

  • MySQL默认采用的是Innodb。(5.5+)

  • MyISAM不支持事务,而InnoDB支持。InnoDB的AUTOCOMMIT默认是打开的,即每条SQL语句会默认被封装成一个事务,自动提交,这样会影响速度,所以最好是把多条SQL语句显示放在begin和commit之间,组成一个事务去提交。

  • InnoDB支持数据行锁定,MyISAM不支持行锁定,只支持锁定整个表。即 MyISAM同一个表上的读锁和写锁是互斥的,MyISAM并发读写时如果等待队列中既有读请求又有写请求,默认写请求的优先级高,即使读请求先到,所以 MyISAM不适合于有大量查询和修改并存的情况,那样查询进程会长时间阻塞。因为MyISAM是锁表,所以某项读操作比较耗时会使其他写进程饿死。

  • InnoDB支持外键,MyISAM不支持。

  • InnoDB的主键范围更大,最大是MyISAM的2倍。

  • InnoDB不支持全文索引,而MyISAM支持。全文索引是指对char、 varchar和text中的每个词(停用词除外)建立倒排序索引。MyISAM的全文索引其实没啥用,因为它不支持中文分词,必须由使用者分词后加入空 格再写到数据表里,而且少于4个汉字的词会和停用词一样被忽略掉。

  • 没有where的count(*)使用MyISAM要比InnoDB快得多。因为MyISAM内置了一个计数器,count(*)时它直接从计数器中读,而InnoDB必须扫描全表。所以在InnoDB上执行count(*)时一般 要伴随where,且where中要包含主键以外的索引列。为什么这里特别强调“主键以外”?因为InnoDB中primary index是和raw data存放在一起的,而secondary index则是单独存放,然后有个指针指向primary key。所以只是count(*)的话使用secondary index扫描更快,而primary key则主要在扫描索引同时要返回raw data时的作用较大。

  • Innodb 不仅仅缓存索引,同时还会缓存实际的数据。

通过以下指令,我们可以看出Mysql的引擎到底是什么:

不删库不跑路 -- 数据库优化

通过下面指令可以知道自己所使用的mysql版本是什么:

不删库不跑路 -- 数据库优化


不删库不跑路 -- 数据库优化
二、优化标准
不删库不跑路 -- 数据库优化

2.1Mysql 物理结构

这里,首先看一张图了解一下Mysql的物理结构:

不删库不跑路 -- 数据库优化


1.最上层是一些客户端和连接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于tcp/ip的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务 器也会为安全接入的每个客户端验证它所具有的操作权限。


2.第二层架构主要完成大多少的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化及部分内置函数的执行。所有跨存储引擎的功能也 在这一层实现,如过程、函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定查询表的顺序,是否利用索引等,最后生成相 应的执行操作。如果是select语句,服务器还会查询内部的缓存。如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。


3.存储引擎层,存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。


4.数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

2.2Explain语句

衡量sql语句的好坏,大家第一个想到的就应该是Explain语句,通过Explain可以看到SQL的基本信息:

有以下几个重点信息需要我们关注:

select_type:
select查询的类型,主要是区别普通查询和联合查询、子查询之类的复杂查询。

type:
访问类型,是较为重要的一个指标,结果值从好到坏依次是:
system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

(1)SYSTEM

CONST的特例,当表上只有一条元组匹配

(2)CONST

WHERE条件筛选后表上至多有一条元组匹配时,比如WHERE ID = 2 (ID是主键,值为2的要么有一条要么没有)

(3)EQ_REF
(4)REF

可以用于单表扫描或者连接。参与连接运算的表,是内表。(在代码实现的算法中,两表连接时作为循环中的内循环遍历的对象,这样的表称为内表)。
基于索引(连接字段上的索引是非唯一索引,操作符必须是“=”谓词,连接字段值不可为NULL)做扫描,使得对外表的一条元组,内表可有若干条元组与之对应。

(5)REF_OR_NULL

类似REF,只是搜索条件包括:连接字段的值可以为NULL的情况,比如 where col = 2 or col is null

(6)INDEX_MERGE

多重范围扫描。两表连接的每个表的连接字段上均有索引存在且索引有序,结果合并在一起。适用于作集合的并、交操作

(7)RANGE

范围扫描,基于索引做范围扫描,为诸如BETWEEN,IN,>=,LIKE类操作提供支持

(8)INDEX_SCAN

索引做扫描,是基于索引在索引的叶子节点上找满足条件的数据(不需要访问数据文件)

(9)UNIQUE_SUBQUERY

在子查询中,基于唯一索引进行扫描,类似于EQ_REF
(10)INDEX_SUBQUERY

在子查询中,基于除唯一索引之外的索引进行扫描
  (11)   Index

该联接类型与ALL相同,除了只有索引树被扫描,扫描全表的顺序是按照索引顺序扫描

(12)ALL

全表扫描或者范围扫描:不使用索引,顺序扫描,直接读取表上的数据(访问数据文件)

rows:
这个数表示mysql要遍历多少数据才能找到。(参考,未必准确)

ref:
显示使用哪个列或常数与key一起从表中选择行。

extra:
Only index:这意味着信息只用索引树中的信息检索出的,这比扫描整个表要快。
using where:就是使用上了where限制。
impossible where:表示用不着where,一般就是没查出来啥。
Using filesort/Using temporary:性能很差,WHERE和ORDER BY的索引经常无法兼顾,如果按照WHERE来确定索引,那么在ORDER BY时,就必然会引起Using filesort,这就要看是先过滤再排序划算,还是先排序再过滤划算。
union merge:index 交集


文末给大家提一个小的问题,欢迎大家后台留言和小强探讨这个问题:

假设一个table中有一列col是varchar(35)类型的,并且这一列有索引,那么如下的sql会走到索引吗?以及为什么呢?

  1. select * from table where col='abc';

  2. select * from table where col=abc;


本文简单介绍道这里,接下来的文章,你将能看到以下精彩内容:Mysql中到底哪些语句可以用到索引,InnoDB事务、锁机制等内容。


近期热文:






以上是关于不删库不跑路 -- 数据库优化的主要内容,如果未能解决你的问题,请参考以下文章

删库不跑路:我含泪写下了 MySQL 数据恢复大法…

删库不跑路!我含泪写下了 MySQL 数据恢复大法…

删库不跑路!我含泪写下了 MySQL 数据恢复大法…

手把手教你玩 MySQL 删库不跑路,直接把 MySQL 的 binlog 玩溜

手把手教你玩 MySQL 删库不跑路,直接把 MySQL 的 binlog 玩溜

删库了,我不跑路,就是玩儿