- 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线程库