MySQL优化

  • 1.数据库(表)的设计合理(3NF)三范式(规范的模式)
  • 2.SQL语句的优化
  • 3.数据库的配置表结构
  • 4.适当硬件配置和操作系统

这个顺序也表现了这四个工作对性能影响的大小

一.数据库表设计(3NF)

通俗的理解为三个范式,对于数据库设计大有好处。三个范式中顺序1NF(2NF(3NF))

第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可分割;(只要是关系型数据库(oracle,Mysql)都满足1NF)

不可分割:关系型数据库列名使用的属性不可分割

第二范式:2NF是对记录的唯一性约束,要求记录有唯一标识,即实体的唯一性

唯一性约束:你的同一张表 不可能出现完全相同的记录(要求每个表都要有主键)

第三范式:3NF是对字段冗余性(数据重复)的约束,即任何字段不能由其他字段派生出来,

它要求字段没有冗余 没有冗余的数据库设计可以做到 通过外键来处理

逆范式(扩展)

逆范式化指的是通过增加冗余或重复的数据来提高数据库的读性能

二.SQL语句优化

SQL语句的种类

①Data Ddefinition Language(DDL)数据定义语句

定义:Create ; 修改:Alter ; 删除:Drop

②Data Query Language (DQL) 数据查询语句

SQL的数据查询语言主要用来对数据库中的各种数据对象进行查询。

SELECT

简单查询

仅含有SELECT子句和FROM子句的查询就是简单查询。

FROM子句指定查询的表

SELECT子句指定查询的列

连接查询

③Data Manipulation Language (DML) 数据操纵语言

插入:INSERT; 删除:DALETE ;修改:UPDATE

TRUNCATE语句

使用TRUNCATE,删除表中的所有数据,比DELETE快。

TRUNCATE 语句不能被撤销

④Data Control Language (DCL) 数据控制功能

SQL的数据控制语言,对表和视图的授权,完整性规则的描述以及事务开始和结束等控制语句。

授权:GRANT ; 回收授权: REVOKE ;

⑤Data Transaction Language(DTL) 数据事务语句

开始事务:BEGIN ;回滚事务:ROLLBACK ;提交事务:COMMIT ;

mysql性能调优过程中经常用到的三件利器

1.慢查询 (分析出现出问题的sql)

慢查询优化

1.1索引没起作用的情况

   在使用like关键字时,如果匹配字符串的第一个字符为”%”,索引不会起作用。只有”%”不在第一个位置索引才会起作用

1.2使用多列索引的查询语句

MySQL可以为多个字段创建索引。一个索引最多可以包括16个字段。对于多列索引,只有查询条件使用了这些字段中的第一个字段时,索引才会被使用

2、Explain (显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句)

3、Profile(查询到 SQL 会执行多少时间, 并看出 CPU/Memory 使用量, 执行过程中 Systemlock, Table lock 花多少时间等等.)

五个原则

①减少数据访问: 设置合理的字段类型,启用压缩,通过索引访问等减少磁盘IO

②返回更少的数据: 只返回需要的字段和数据分页处理 减少磁盘io及网络io

③减少交互次数: 批量DML操作,函数存储等减少数据连接次数

④减少服务器CPU开销: 尽量减少数据库排序操作以及全表查询,减少cpu 内存占用

⑤利用更多资源: 使用表分区,可以增加并行操作,更大限度利用cpu资源

  • 避免不走索引的场景

1.尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描

2. 尽量避免使用in 和not in,会导致引擎走全表扫描

3. 尽量避免使用 or,会导致数据库引擎放弃索引进行全表扫描

4. 尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描

5.尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描

6. 当数据量大时,避免使用where 1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描

7. 查询条件不能用 <> 或者 !=

8. where条件仅包含复合索引非前置列

9. 隐式类型转换造成不使用索引 

10. order by 条件要与where中条件一致,否则order by不会利用索引进行排序

11. 正确使用hint优化语句

  • SELECT语句其他优化

1. 避免出现select *

2. 避免出现不确定结果的函数

3.多表关联查询时,小表在前,大表在后。

4. 使用表的别名

5. 用where字句替换HAVING字句

6.调整Where字句中的连接顺序

  • 增删改 DML 语句优化

1. 大批量插入数据

2. 适当使用commit

3. 避免重复查询更新的数据

4.查询优先还是更新(insert、update、delete)优先

  • 查询条件优化

1. 对于复杂的查询,可以使用中间临时表 暂存数据;

2. 优化group by语句

3. 优化join语句

4. 优化union查询

5.拆分复杂SQL为多个小SQL,避免大事务

6. 使用truncate代替delete

7. 使用合理的分页方式以提高分页效率

  • 建表优化

1. 在表中建立索引,优先考虑where、order by使用到的字段。

2. 尽量使用数字型字段(如性别,男:1 女:2),若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。

这是因为引擎在处理查询和连接时会 逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

3. 查询数据量大的表 会造成查询缓慢。主要的原因是扫描行数过多。这个时候可以通过程序,分段分页进行查询,循环遍历,将结果合并处理进行展示。

4. 用varchar/nvarchar 代替 char/nchar

尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

不要以为 NULL 不需要空间,比如:char(100) 型,在字段建立时,空间就固定了, 不管是否插入值(NULL也包含在内),都是占用 100个字符的空间的,如果是varchar这样的变长字段, null 不占用空间。

三.数据库的配置表结构
1.垂直拆分

指的是将一个包含了很多表的数据库,根据表的功能的不同,拆分为多个小的数据库,每个库中包含部分表。

1.1垂直拆分的优点

垂直拆分会使得单个用户请求的响应时间变长,但是会使得整个服务的吞吐量大大的增加。(服务吞吐量即系统在单位时间内处理请求的数量)

1.2垂直拆分的另外2种用途?

1).将一个包含了很多字段的大表拆分为多个小表,每个表中包含部分字段(基本很少遇到)

2).进行服务化(SOA)的改造,除了业务上需要进行拆分,底层的存储也需要进行隔离

2.MySQL读写分离

将数据库分为主库和从库,一个主库用于写数据,多个从库完成读数据的操作。

主从库通过某种机制进行数据的同步。

1.添加数据库中间件降低耦合

2.读写分离,提高数据库响应速度

3.数据库分表分库,更好维护数据

mycat分库分表中间件

系统软件和用户应用软件之间连接的软件

一主一从读写分离

双主双重读写分离

3.水平拆分

通过一种算法,将数据库进行分割的架构。每个分片中的数据没有重合,所有分片中的数据并集组成全部数据。

水平分表实际又可以分为如下三种:只分表、只分库、分库分表

1.只分表:将db库中的一个表拆分为2个分表,即uer_0和user_1

2.只分库:将db库差费为db_0和db_1这2个库,同时在db_0和db_1库中各自新建一个user表,db_0.user表和db_1.user表中各自只存放原来的db.user表中的部分数据

3.分库分表:将db库拆分为db_0和db_1这2个库,db_0中包含user_0、user_1这2个分表,db_1中包含user_2、user_3这2个分表。

为什么需要进行分表分库?

一旦业务表中的数据量比较大,从维护和性能的角度来看,仍然无法掩盖因为数据量过大从而导致数据库性能下降的事实。因此,这个时候mysql DBA就该对数据库进行水平分区,经过水平分区设置后的业务表,必然能够将原本一张表维护的海量数据分配给N个子表进行存储和维护。

分表分库的使用场景?

如果库中的多个表中只有某张表或者少量表数据量过大,那么只需要针对这些表进行拆分,其它表保持不变。

分库分表的好处?

如果说读写分离实现数据库读能力的水平提升

那么,分库分表是是吸纳数据库写能力的水平提升

四.适当硬件配置和操作系统

1. CPU 那个更好,更快的CPU还是更多的CPU?

当遇到CPU密集型的工作时候,mysql通常可以从更快的CPU中获益. 而,备库的话,一般是i/o密集型,因为主库和从库之间是单线程 多CPU在联机事务处理(OLTP)系统中非常有用

2. 平衡内存和磁盘资源

配置大量内存原因其实不是因为可以在内存中保存大量数据,而最终目的是避免磁盘I/O

当所有数据放到内存中,此时服务器”热”起来,所有的读取操作都会缓存命中,换句话说,缓存可延迟写入此时便会出现缓存命中率,可以使用CPU利用率来判断缓存命中

3. 随机的I/O和顺序的I/O

顺序操作的执行速度比随机操作的块,无论在内存还是磁盘

所以增加内存是解决随机I/O读取问题的最好办法,如果有足够的内存,就可以完全避免磁盘的读取请求.存储引擎的顺序读比随机读快。

4.  使用固态硬盘(闪存)

什么情况下使用闪存?

有着大量随机I/O工作负载场景下,造成大量随机I/O的情况是由于数据大于服务器内存导致的.

优化固态硬盘上的mysql

1,增加innoDB的I/O容量 增加I/O线程数到10-15

2,增加innodb的日志文件,以帮助提升和稳定性能(4G)

3,把一些存储从闪存转移到RAID,并且ibdata1也适合放到raid卷上,而且可以利用percona server 特性使用4kb的块写事务日志,而不是默认的521字节。因为这会匹配大部分的闪存本身的块大小,以获得更好的效果

4,限制插入缓冲大小,innoDB中变更为change buffer,而不是无限增大,并避免ibdata1变得非常大。

5. raid的性能优化:不做过多的记录

raid5 本身的优化已经可以达到raid10的性能。没钱用raid5 有钱用raid10

做raid阵列的监控。以便提醒硬盘或者raid卷降级或者失效

6. 优化网络以提升mysql性能

DNS配置 尽量使用skip-name-resolve来减少因解析带来的不必要麻烦、

检查网络的ping 丢包率

可以缩短tcp保持状态的超时时间,默认1分钟

7.线程

新版的mysql默认都使用了新的原生的POSIX线程库

订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
滚动至顶部