数据库架构设计与优化
导航:
- 数据库架构设计与优化
- 一. 影响数据库性能的原因
- 二. 什么影响了MYSQL性能
- 2.1 影响性能的几个方面
- 2.2 CPU资源和可用内存大小
- 2.3 使用RAID增加传统机器硬盘的性能
- 2.3.2 RAID 0
- 2.3.5 RAID 10 又称分片的镜像
- 2.3.6 对常用RAID的解析
- 2.4 使用固态存储或PCle卡
- 2.5 网络存储SAN和NAS
- 2.6 服务器硬件对性能的影响
- 2.7 操作系统对性能的参数优化
- 2.8 文件系统对性能的影响
- 2.9 Mysql体系结构
- 2.10 Mysql常用存储引擎之MyISAM
- 2.11 MySQL常用存储引擎之InnoDB
- 2.12 MySQL常用存储引擎之CSV
- 2.13 MySQL常用存储引擎之Archive
- 2.14 MySQL常用存储引擎之Memory
- 2.15 MySQL常用存储引擎之Federated
- 2.16 如何选择存储引擎?
- 2.17 服务器参数介绍
- 2.18 内存配置相关参数
- 2.19 其他常用参数
- 2.20 数据库设计对性能的影响
- 三. 基准测试
- 四. 数据库结构优化
- 五. MySQL高可用架构设计
- 六. 数据库索引优化
- 七. SQL查询优化
- 八. 数据库的分库分表
- 九. 数据库监控
一. 影响数据库性能的原因
1.1 影响数据库的因素
- SQL查询速度
- 服务器硬件
- 网卡流量
- 磁盘IO
1.2 影响MYSQL性能的因素有哪些?
- 超高的QPS和TPS
- 风险:效率低下的SQL(每运行一次SQL只能使用一个CPU,所以单个SQL效率低下影响CPU执行效率)
QPS:每秒中的查询量。 80%的事故都是因为慢查询造成的
- 大量的并发和超高的CPU使用率
- 大量的并发:
- 数据库连接数被占满(max_connections默认100)
- 超高的CPU使用率:
- 因CPU资源耗尽出现宕机
- 大量的并发:
- 磁盘IO
- 磁盘IO性能突然下降(使用更快的磁盘设备)
- 其他大量消耗磁盘性能的计划任务(调整计划任务,做好磁盘维护)
- 网卡流量:
- 网卡IO被占满
- 如何避免无法连接数据库的情况:
- 减少从服务器的数量
- 进行分集缓存
- 避免使用 select * 进行查询
- 分离业务网络和服务器网络
- 如何避免无法连接数据库的情况:
- 网卡IO被占满
- 大表
- 什么样的表可以称之为大表
- 记录行数巨大,单表超过千万行
- 表数据文件巨大,表数据文件超过10G
大表对查询的影响: 慢查询->很难在一定时间内过滤出所需要的数据
- 大表对DDL操作的影响:
- 建立索引需要很长时间
- MYSQL版本<5.5建立索引会锁表
- MYSQL版本>=5.5 虽然不会锁表但会引起主从延迟
- 修改表结构需要长时间锁表
- 会造成长时间的主从延迟
- 影响正常的数据操作
- 如何处理数据库中的大表:
- 分库分表:
- 把一张大表分成多个小表
难点: 分表主键的选择 分表后跨分区数据的查询和统计
- 大表的历史数据归档
- 减少对前后端业务的影响
归档时间点的选择
如何进行归档操作
- 分库分表:
- 建立索引需要很长时间
- 什么样的表可以称之为大表
1.3 事务
- 什么是事务?
- 事务是数据库系统区别于其他一切文件系统的重要特性之一。
- 事务是一组具有原子性的SQL语句,或是一个独立的工作单元。
- 事务符合哪些特性?
-
事务的原子性
- 定义:一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败,对于一个事务来说,不可能只执行其中的一部分操作;
-
事务的一致性
- 定义:一致性是指事务将从数据库从一种一致性状态转换到另外一种一致性住哪个台,在事务开始之前和事务结束后数据库中数据的完整性没有被破坏;
-
事务的隔离性:
- 定义:隔离性要求一个事务对数据库中数据的修改,在未提交完成前对于其他事务是不可见的。
- SQL标准中定义的四种隔离级别:
- 未提交读(READ UNCOMMITED)
- 已提交度(READ COMMITED)
- 可重复读(REPEATABLE READ)
- 可串行化(SERIALIZABLE)
并发性由高到低,隔离性能由低到高
-
事务的持久性:
- 定义: 一旦事务提交,则其所作的修改就会永久保存到数据库中。此时即使系统崩溃,已经提交的修改数据也不会丢失。
-
- 什么是大事务?
- 定义:运行时间比较长,操作的数据比较多的事务;
- 风险:
- 锁定太多的数据,造成大量的阻塞和锁超时;
- 回滚时所需时间比较长
- 执行时间长,容易造成主从延迟
- 如何处理大事务:
- 避免一次处理太多数据
- 移除不必要在事务中的SELECT(让事务中只有写入或者修改操作,select可以不用在事务中完成
二. 什么影响了MYSQL性能
2.1 影响性能的几个方面
- 服务器硬件
- 服务器系统
- 数据库存储引擎的选择
- MyISAM:不支持事务,表级锁;
- InnoDB:事务级存储引擎,完美支持行级锁,事务ACID特性;
- 数据库参数配置
- 数据库结构设计和SQL语句
2.2 CPU资源和可用内存大小
-
如何选择CPU?
- 买单核性能更好的CPU。 因为MYSQL不支持多CPU对同一SQL并发处理,所以我们买多核对其帮助不大,更应该考虑单CPU性能更高的CPU
- 要考虑MYSQL版本。因为新版本对多核的支持更加好。要根据自己的版本进行选择
- 选择64位的CPU。因为MYSQL单线程的,使用32位对其有极大的限制。所以用64位更好。
mysql不支持多cpu对同一SQL并发处理
-
如何选择内存?
- 要选择主板支持的最大内存频率;(频率越高,速度越快)
- 购买要点:
- 组成购买升级
- 每个通道的内存:相同品牌、颗粒
- 频率、电压、校验技术和型号
- 单条容量要尽可能大
- 根据数据库大小选择内存;
-
磁盘的配置和选择:
- 常见的磁盘种类:
- 传统机器磁盘
- 使用RAID增强传统机器硬盘的性能
- 使用固态存储SSD和PCIe卡
- 使用网络存储NAS和SAN
- 传统机器硬盘:
- 特点:最常见,使用最多,价格低,存储空间大,读、写较慢;
- 传统磁盘读取过程:
- 移动磁头到磁盘表面上的正确位置;
- 等待磁盘旋转,使的所需的数据在磁头之下;
- 等待磁盘旋转过去,所有所需的数据都被磁头读出;
- 如何选择传统机器硬盘
- 存储容量
- 传输速度
- 访问时间
- 主轴转速
- 物理尺寸(越大,存储空间越大)
- 常见的磁盘种类:
-
常用MySQL存储引擎:
- MyISAM:
2.InnoDB:
- MyISAM:
2.3 使用RAID增加传统机器硬盘的性能
2.3.1 什么是RAID?
- RAID是磁盘冗余队列的简称(Redundant Arrays of Independent Disks)简单来说RAID的作用就是可以把多个容量较小的餐盘组成一组容量更大的磁盘,并提供数据冗余来保证数据完整性的技术。
2.3.2 RAID 0
- RAID 0 是最早出现的RAID模式,也称之为数据条带。是组建磁盘阵列中最简单的一种形式,只需要2块以上的硬盘即可,成本低,可以提高整个磁盘的性能和吞吐量。RAID 0 没有提供冗余或错误修复能力,但是实现成本是最低的。
- 如图所示:
2.3.3 RAID 1
- RAID 1 又称磁盘镜像,原理是把一个磁盘的数据镜像到另一个磁盘上,也就是说数据在写入一块磁盘的同时,会在另一块闲置的磁盘上生成镜像文件,在不影响性能情况下最大限度的保证系统的可靠性和可修复性。
- 如图所示:
2.3.4 RAID 5
- RAID 5又称之为分布式奇偶校验磁盘阵列
- 通过分布式奇偶校验块把数据分散到多个磁盘上,这样如果任何一个盘数据失效,都可以从奇偶校验块中重建。但是如果两块磁盘失效,则整个卷的数据都无法恢复。
- 如图所示:
使用在从服务器上,适合读。
2.3.5 RAID 10 又称分片的镜像
- 它是对磁盘先做RAID 1 之后对两组RAID 1的磁盘再做RAID 0 ,所以对读写都有良好的性能,相对于RAID 5 重建起来更简单,速度也更快。
- 如图所示:
2.3.6 对常用RAID的解析
- 常用RAID如图:
- RAID级别的选择:
2.4 使用固态存储或PCle卡
-
固态存储相比于机械磁盘的特点:
- 相比机械磁盘,固态磁盘有更好的随机读写性能(优点)
- 相比机械磁盘,固态磁盘能更好的支持并发(优点)
- 相比机械磁盘固态磁盘更容易损坏(缺点)
-
固态硬盘的特点:
- 使用SATA接口,可以替换传统磁盘而不需任何改变
- SATA接口的SSD同样支持RAID技术
由于使用SATA 接口,而STATA 有3.0 和2.0 ,如果连接的是2.0接口,则会本身的速度受到限制。
-
PCIe卡图示:
-
固态存储PCIe卡的特点
- 无法使用SATA接口,需要独特的驱动和配置
- 价格相对于SSD要贵,但是性能比SSD更好
不建议使用RAID,成本较高; PCIe卡会消耗内存;
-
固态存储的使用场景:
- 适用于存在大量随机I/O的场景
- 使用于解决单线程负载的I/O瓶颈
2.5 网络存储SAN和NAS
-
概述:SAN(Storage Area Network) 和 NAS(Network-Attached Storage)是两种外部文件存储设备加载到服务器上的方法。
-
SAN:
- 图示:
- SAN设备通过光纤连接到服务器,设备通过块接口访问,服务器可以将其当做硬盘使用。
- 特点:
- 大量顺序读写
- 读写I/O
- 缓存
- I/O合并
- 随机读写/慢
- 不如本地RAID磁盘
- 图示:
-
NAS:
- NAS设备使用网络连接,通过基于文件的协议如NFS或SMB来访问。
-
网络存储适用的场景:
- 数据库备份
-
网络对性能的影响:
- 网络带宽对性能的影响
- 网络质量对性能的影响
-
建议:
- 采用高性能和高带宽的网络接口设备和交换机
- 对多个网卡进行绑定,增强可用性和带宽
- 尽可能的进行网络隔离
mysql 的性能瓶颈一般是在随机读写上,而网络存储的优势在于顺序读写,而不是随机读写,所以并不太适用于做为Mysql存储;
2.6 服务器硬件对性能的影响
-
CPU:
- 64位的CPU一定要工作在64位的系统下
- 对于并发比较高的场景CPU的数量比频率重要
- 对于CPU密集性场景和复杂SQL则频率越高越好
-
内存:
- 选择主板能使用的最高频率的内存。
- 内存的大小对性能很重要,所以尽可能的要大。
-
I/O子系统:
- PCIe-> SSD->RAID10->磁盘->SAN
2.7 操作系统对性能的参数优化
-
MYSQL适合的操作系统
- Windows FreeBSD Solaris Linux
本文章的演示都是在Centos上进行演示的,也建议使用Linux系统;
-
内核相关参数(/etc/sysct.conf)
- 网络相关的参数:
- net.core.somaxconn=65535
- net.core.netdev_max_backlog=65535
- net.ipv4.tcp_max_syn_backlog=65535
根据需要调整
- 加快tcp回收速度,连接时间
- net.ipv4.tcp_fin_timeout=10
- net.ipv4.tcp_tw_reuse=1
- net.ipv4.tcp_tw_recycle=1
- tcp 接收和发送的缓冲区默认值:
- 用于失效连接减少tcp资源占用数量,
- 用于失效连接减少tcp资源占用数量,
- 网络相关的参数:
-
内存优化:
kernel.shmmax=4294967295
- 这个参数应该设置的足够大,以便能在一个共享内存段下容纳下整个的InnoDB缓冲池的大小。 2. 这个值的大小对于64位Linux系统,可取的最大值为物理内存置-1byte,建议值为大于物理内存的一般,一般取值大于Innodb缓冲池的大小即可,可以取物理内存-1byte
vm.swappiness=0
- 就是告诉Linux内核,除非虚拟内存完全满了,否则不要使用交换区;
- 当操作系统因为没有足够的内存时就会将一些虚拟内存写到磁盘的交换区中这样就会发生内存交换。
- 使用交换分区后,mysql的性能会大幅下降,可能会导致一些灾难性的后果。所以在Mysql服务器上是否要使用交换分区有一些争议:在MySQL服务所在的Linux系统上完全禁用交换分区。
- 带来的风险:
- 降低操作系统的性能
- 容易造成内存溢出、崩溃、或都被操作系统Kill掉。
- 结论:
- 在MySQL服务器上保留交换区还是很必要的,但是要控制何时使用交换分区。
-
其他优化:
- 增加资源限制:
结论: 把可打开的文件数量增加到了65535个以保证可以打开足够多的文件句柄。 注意: 这个文件的修改需要重启系统才可以生效。
- 磁盘调度策略:
- 增加资源限制:
2.8 文件系统对性能的影响
- 各个系统支持的文件系统格式:
- EXT3/4系统的挂载参数(/etc/fstab)
data= writeback | ordered | journal
noatime, nodiratime
/dev/sda1/ext4 noatime,nodiratime,data=writeback 11
2.9 Mysql体系结构
- 插件式存储引擎
- 客户端:PHP ,JAVA,C API, .Net以及ODBC, JDBC等
- 查询流程图示:
- select:要查询的数据,这个具体的实现的方式则是由下一层存储引擎层来实现。
2.10 Mysql常用存储引擎之MyISAM
-
Mysql 5.5 之前版本默认存储引擎;它也是系统表和临时表的默认存储引擎;
-
临时表:
- 在排序、分组等操作中,当数量超过一定的大小之后,由查询优化器建立的临时表。
- MyISAM存储引擎表由MYD和MYI组成
-
特性:
- 并发性与锁级别
- 表损坏修复
~~~java
check table tablename
repair table tablename
~~~
- MyISAM表支持的索引类型
- MyISAM表支持数据压缩
- 命令行: myisampack -
限制:
- 版本 < Mysql 5.0 时默认表大小为4G
- 如存储大表则要修改MAX_Rows和AVG_ROW_LENGTH
- 版本> MySQL 5.0 时默认支持为256TB
-
适用场景:
- 非事务型应用
- 只读类应用
- 空间类应用
2.11 MySQL常用存储引擎之InnoDB
-
MySQL 5.5 及之后版本默认存储引擎: InnoDb表
- innodb_file_per_table
- ON:独立表空间:tablename.ibd
- OFF:系统表空间:ibdataX
-
系统表空间和独立表空间要如何选择:
-[ ] 收缩方面:
- 系统表空间无法简单的收缩文件大小
- 独立表空间可以通过optimize table 命令收缩系统文件- IO方面
- 系统表空间会产生IO瓶颈
- 独立表空间
- IO方面
-
建议:
- 对InnoDB使用独立表空间
-
步骤:[把原来存在于系统表空间中的表转移到独立表空间中的方法]
- 使用mysqldump导出所有数据库表数据
- 停止MySQL服务,修改参数,并删除Innodb相关文件
- 重启MySQL服务,重建Innodb系统表空间
- 重新导入数据
-
系统表空间和独立表空间要如何选择
- Innodb数据字典信息
- Undo 回滚段
-
Innodb存储引擎的特性
-
Innodb是一种事务性存储引擎
-
完全支持事务的ACID特性
-
Redo Log 和Undo Log
-
Innodb支持行级锁
-
行级锁可以最大程度的支持并发
-
行级锁是由存储引擎层实现的
-
-
什么是锁?
- 锁对主要作用是管理共享资源的并发访问
- 锁用于实现事务的隔离性
-
锁的类型:
- 共享锁(也成读锁)
- 独占锁(也成写锁)
- 图示:
-
锁的粒度:
- 表级锁
- 行级锁
-
阻塞和死锁
- 什么是阻塞?
- 一个锁锁上了,其他的请求无法对此资源进行访问,则为阻塞;相当于一个屋子外被锁上了,其他人不能进入这个屋子;
会导致堆积,占用大量资源;
- 什么是死锁?
- 指的是两个或者两个以上的事务相互占用对方的锁而导致异常。
死锁的发生后,系统能自动发现并处理。但是大量的死锁出现,我们就需要警惕了。
- 什么是阻塞?
-
Innodb状态检查
- show engine innodb status
-
适用场景:
- Innodb适合于大多数OLTP应用
2.12 MySQL常用存储引擎之CSV
-
文件系统存储特点
- 数据以文本方式存储在文件中
- .CSV文件存储表内容
- .CSM文件存储表内容
- .CSM文件存储表的元数据如表状态和数据量
- .frm文件存储表结构信息
-
特点:
- 以CSV格式进行数据存储
- 所有列必须都是不能为NULL的
- 不支持索引 -> 不支持大表,不适合在线处理
- 可以对数据文件直接编辑
-
适用场景:
- 适合作为数据交换的中间表
- 图示:
-
2.13 MySQL常用存储引擎之Archive
-
文件系统存储特点:
- 以zlib对表数据进行压缩,磁盘I/O更少
- 数据存储在ARZ为后缀的文件中
-
Archive存储引擎的特点
- 只支持insert和select操作
- 只允许在自增ID列上加索引
-
使用场景:
- 日志和数据采集类应用
2.14 MySQL常用存储引擎之Memory
-
文件系统存储特点:
- 也称HEAP存储引擎,所以数据保存在内存汇总
-
功能特点:
- 支持HASH索引和BTree索引(等值查找使用HASH,范围查找使用BTree)
- 所有字段都会固定长度varchar(10)=char(10)
- 不支持BLOG和TEXT等大字段
- Memory存储引擎使用表级锁;
- 最大大小由 max_heap_table_size参数决定
-
容易混淆的概念
- 图示:
- 图示:
-
使用场景
- 用于查找或者是映射表,例如邮编和地区的对应表
- 用于保存数据分析中产生的中间表
- 用于缓存周期性聚合数据的结果表
Memory数据易丢失,所以要求数据可再生。
2.15 MySQL常用存储引擎之Federated
-
特点:
- 提供了访问远程MySQL服务器上表的方法
- 本地不存储数据,数据全部放到远程服务器上
- 本地需要保存表结构和远程服务器的连接信息
-
如何使用:
- 默认禁止,启动需要在启动时增加federated参数
mysql://user_name[:password]@host_name[:port_num]/db_name/tbl_name
-
使用场景:
- 偶尔的统计分析及手工查询
2.16 如何选择存储引擎?
-
概述: 大部分的话我们使用Innodb存储引擎即可,除非是一些Innodb引擎不支持的功能,则可以使用其他的引擎;
-
参考条件:
- 事务;
- 备份;
- 崩溃恢复
- 存储引擎的特有特性
2.17 服务器参数介绍
-
大部分的服务器参数使用默认即可,小部分的可以根据服务器配置来进行调整;
-
MySQL获取配置信息路径:
- 命令行参数:
mysqld_safe --datadir=/data/sql_data
- 配置文件
mysqld --help --verbose | grep -A 1 'Default options'
/etc/my.cnf/etc/mysql/my.cnf/home/mysql/my.cnf~/.my.cnf
- MySQL配置参数的作用域:
- 全局参数:
- 全局参数:
- 命令行参数:
2.18 内存配置相关参数
-
要点:
- 确定可以使用的内存的上限
- 确定MySQL的每个链接使用的内存
- 如图:
- 如图:
-
内存配置相关参数:
- 确定需要为操作系统保留多少内存
- 如何为缓存池分配内存:
- Innodb_buffer_pool_size
总内存-(每个线程所需要的内存*链接数)- 系统保留内存
- key_buffer_size
- 常用相关命令:
- 日志相关:
Innodb_flush_log_at_trx_commit
- 0:每秒进行一次log写入cache,并flush log到磁盘
- 1[默认]:在每次事务提交执行log写入cache,并flush log到磁盘
- 2[建议]:每次事务提交,执行log数据写入到cache,每秒执行一次flush log到磁盘;
Innodb_flush_method=O_DIRECT
- // 刷新方式,决定了如何写和如何刷。关闭读写,避免双重缓存,建议Linux使用
- Innodb_file_per_table=1
- // 建议使用,为每个表建立表空间
Innodb_doublewrite=1
- 启用双写缓存,增强数据安全性
delay_key_write
- OFF:每次写操作后刷新键缓冲中的脏块到磁盘
- ON:只对在键表时指定了delay_key_write选项的表使用延迟刷新
- ALL:对所有MYISAM表都使用延迟键写入;
- 安全相关配置参数:
- expire_logs_days 指定自动清理binlog的天数
- max_allowed_packet 控制MySQL可以接收包的大小
- skip_name_resolve 禁用DNS查找
- sysdate_is_now 确保sysdate()返回确定性日期
- read_only 禁止非super权限的用户写权限
- skip_slave_start 禁用Slave自动恢复
- sql_mode 设置MySQL所使用的SQL模式
- strict_trans_tables
- no_engine_subtitution
- no_zero_date
- no_zero_in_date
- only_full_group_by
不要轻易改动,以免生产环境出错
- 日志相关:
2.19 其他常用参数
- sync_binlog 控制MYSQL如何向磁盘刷新binlog
- tmp_table_size 和 max_heap_table_size 控制内存临时表大小
- max_connections 控制允许的最大连接数
2.20 数据库设计对性能的影响
-
数据库设计对设计的影响
- 过分的反范式话为表建立太多的列
- 过分的范式化造成太多的表关联
- 在OLTP环境中使用不恰当的分区表
- 使用外键保证数据的完整性
-
性能优化顺序
- 数据库结构设计和SQL语句
- 数据库存储引擎的选择和参数配置
- 系统选择及优化
- 硬件升级
三. 基准测试
3.1 什么是基准测试
- 定义:基准测试是一种测量和评估软件性能指标的活动用于建立某个时刻的性能基准,以便当系统发生软硬件变化时重新进行基准测试以评估变化对性能的影响
总结来说,基准测试是针对系统设置的一种压力测试
- 基准测试与压力测试的对比:
- 基准测试:直接、简单、易于比较,用于评估服务器的处理能力
- 压力测试:对真实的业务数据进行测试,获得真实系统所能承受的压力
压力测试需要针对不同主题,所使用的数据和查询也是真实用到的;基准测试可能不关心业务逻辑,所使用的查询和业务的真实性可以和业务环境没关系。
3.2 如何进行基准测试
- 基准测试的目的:
- 建立MySQL服务器的性能基准线
确定当前MySQL服务器运行情况
- 模拟比当前系统更高的负载,以找出系统的扩展瓶颈
增加数据库并发,观察QPS,TPS变化,确定并发量与性能最优的关系
- 测试不同的硬件、软件和操作系统配置
- 证明新的硬件设备是否配置正确
- 建立MySQL服务器的性能基准线
- 如何进行基准测试:
- 对整个系统进行基准测试
- 从系统入口进行测试(如网站Web前端,手机APP前端)
- 优缺点:
- 优点:
- 能够测试整个系统的性能,包括web服务器缓存、数据库等。
- 能反映出系统中各个组件接口间的性能问题体现真实性能状况
- 缺点:
- 测试设计复杂,消耗时间长
- 优点:
- 单独对MySQL进行基准测试:
- 优点:
- 测试设计简单,所需耗费时间短
- 缺点:
- 无法全面了解整个系统的性能基线
- 优点:
- 对整个系统进行基准测试
3.3 MySQL基准测试的常见指标
- 单位时间所处理的事务数(TPS)
- 单位时间内所处理的查询数(QPS)
- 响应时间
- 并发量: 同时处理查询请求的数量
正在工作中的并发的操作数或同时工作的数量
3.4 基准测试的步骤
- 计划和设计基准测试
- 对整个系统还是某一组件
- 使用什么样的数据
- 准备基准测试及数据收集脚本
- CPU使用率、IO、网络流量、状态与计数器等
- Get_Test_info.sh
- 运行基准测试:
- 使用生产环境数据时只使用了部分数据
- 在多用户场景中,只做单用户的测试
推荐多线程并发测试
3.5 基准测试中容易忽略的问题
- 使用生产环境数据时只使用了部分数据
推荐: 使用数据库完全备份来测试
- 在多用户场景中,只做单用户的测试
推荐:使用多线程并发测试
- 在单服务器上测试分布式应用
推荐:使用相同架构进行测试
- 反复执行同一查询
容易缓存命中,无法反应查询真实性能
3.6 常用的基准测试工具介绍
-
MySQL基准测试工作之 mysqlslap
-
下载及安装:
- MySQL服务器自带的基准测试工具,随MySQL一起安装
-
特点:
- 可以模拟服务器负载,并输出相关统计信息
- 可以指定也可以自动生成查询语句
-
常用参数说明:
- –auto-generate-sql 由系统自动生成SQL脚本进行测试
- –auto-generate-sql-add-autoincrement 在生成的表中增加自增ID
- –auto-generate-sql-load-type 指定测试中使用的查询类型
- –auto-generate-sql-write-number 指定初始化数据数据时生成的数据量
- –concurrency 指定并发线程的数量
- –engine 指定要测试表的存储引擎,可以用逗号分隔多个存储引擎
- –no-drop指定不清理测试数据
- –iterations 指定测试运行的次数
- –number-of-queries 指定每一个线程执行查询的查询数量
- –debug-info 指定输出额外的内存及CPU统计信息
- –number-int-cols 指定测试表中包含的INT类型列的数量
- –number-char-cols 指定测试表中包含的varchar类型的数量
- –create-schema 指定了用于执行测试的数据库的名字
- –query 用于指定自定义SQL的脚本
- –only-print 并不运行测试脚本,而是把生成的脚本打印出来
基准测试的原理就是,通过调用基准测试的相关方法和参数,然后生成表和具体的数据,然后进行测试性能;这一系列的过程是通过设置好参数后会生成一个脚本,而这个脚本就是基准测试的关键;
-
测试示例:
- 检验是否安装了mysqllap工具:
mysqlslap --help
- 编写测试代码:
mysqlslap --concurrency=1,50,100,200 --iterations=3 --number-int-clos=5 --number-char-clos=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=mvisam.innodb --number-of-queries=10 --create-schema=sbtest
注意: --only-print 并不运行测试脚本,而是把生成的脚本打印出来。 在测试过程中,它会模拟一些数据去进行插入,查询等方式去测试性能;
- 检验是否安装了mysqllap工具:
-
-
MySQL基准测试工作之 sysbench
-
多线程测试工具,它的范围更广,更为灵活,并且较为常用的测试工具;需要下载安装后才能进行测试。
-
安装说明:
https://github.com/akopytov/sysbench/archive/0.5.zip
unzip sysbench-0.5.zip
cd sysbench
./autogen.sh
./configure --with-mysql-includes=/usr/local/mysql/include/ \--with-mysql-libs=/usr/local/mysql/lib/
make && make install
-
实战安装操作:
- 假定已经下载好了。并且已经进入下载目录;
- 解压:
unzip sysbench-0.5.zip
- 进入目录:
cd sysbench-0.5
- 执行命令:
./autogen.sh
- 配置安装目录(根据自己的安装目录而定):
./configure --with-mysql-includes=/usr/local/mysql/include/ --with-mysql-libs=/usr/local/mysql/lib
- 输入执行命令:
make
- 输入执行命令:
make install
-
常用参数:
- test 用于指定所要执行的测试类型,支持以下参数:
- Fileio 文件系统I/O性能测试
- cou cou性能测试
- memory 内存性能测试
- Oltp 测试要指定具体的lua脚本
Lua脚本位于sysbench-0.5/sysbench/tests/db
- –mysql-db用于指定执行基准测试的数据库名
- –mysql-table-engine 用于指定所使用的存储引擎
- –oltp-tables-count 执行测试的表的数量
- –oltp-table-size 指定每个表中的数据行数
- –num-threads 指定测试的并发线程数量
- –max-time 指定最大的测试时间
- –report-interval 指定间隔多长时间输出一次统计信息
- –mysql-user 指定执行测试的MySQL用户
- –mysql-password指定执行测试的MySQL用户的密码
- prepare 用于准备测试行数据
- run 用于实际进行测试
- cleanup 用于清理测试数据
- test 用于指定所要执行的测试类型,支持以下参数:
-
实战操作命令:
sysbench --test=./oltp.lua --mysql-table-engine=innodb --oltp-table-size=10000 --mysql-db=表名 --mysql-user=sfbest --mysql-password=123456 --oltp-tables-count=10 --mysql-socket=/usr/local/mysql/data/mysql.sock prepare
-
-
sysbench演示测试示例
- CPU测试:
sysbench --test=cpu --cpu-max-prime=10000 run
- 磁盘IO测试:
- 首先查看内存大小:
- df -lh
- 生成大于磁盘大小的测试文件
sysbench --test=fileio --file-total-size=1G prepare
- 进行测试:
sysbench --test=fileio --num-threads=8 --init-rng=on --file-total-size=1G --file-test-mode=rndrw --report-interval=1 run
每隔一秒就会生成一个结果;
- 注意: 进行测试的语句请根据实际情况来;
- 首先查看内存大小:
- CPU测试:
四. 数据库结构优化
4.1 优化介绍
- 数据库结构优化的目的:
- 减少数据冗余(必要的数据冗余可以忽略)
- 尽量避免数据维护中出现更新,插入和删除异常;
- 插入异常:如果表中的某个实体随着另一个实体的存在而存在;
- 更新异常:如果更改表中的某个实体的单独属性时,需要对多行进行更新;(比如一个用户得分表,将总分从100分提升至150时,需要对每个用户的得分进行更新;)
- 删除异常:如果删除表中的某一实体则会导致其他实体的消息;
使用范式化,能尽量少的减少这些问题的产生;
- 节约数据存储空间
- 提高查询效率;
4.2 数据库结构设计(逻辑设计)
-
数据库结构设计的步骤
- 需求分析: 全面了解产品设计的存储需求,存储需求,数据处理需求,数据的安全性和完整性;
- 设计数据的逻辑存储结构: 数据实体之间的逻辑关系,解决数据冗余
- 物理设计: 根据所使用的数据库特点进行表结构设计
- 关系型数据库: orcale,sqlServer,mysql,postgresSQL
- 非关系型数据库:mongoDB,Redis,Hadoop
- 存储引擎:InnoDB
- 维护优化: 根据实际情况对索引、存储结构等进行优化;
-
数据库设计范式:
- 数据库设计的第一范式:
- 数据库表中的所有字段都只具有单一属性
- 单一属性的列是由基本的数据类型所构成的
- 设计出来的表都是简单的二维表
- 数据库设计的第二范式:
- 要求一个表中只具有一个业务主键,也就是说符合第二范式的表中不能存在非主键列对只对部分主键的依赖关系;
- 数据库设计的第三范式:
- 指每一个非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上消除了非主属性对主键的传递依赖;
范式后面的范式,必须同时满足之前的范式;设计时也要考虑实际情况;
- 数据库设计的第一范式:
-
反范式化设计:
- 反范式化是针对范式化而言的,在前面介绍了数据库设计的范式,所谓的范式,所谓的反范式化就是为了性能和读取效率的考虑而适当的对数据库设计范式的要求进行违反,而允许存在少量的数据冗余,换句话来说反范式化就是使用空间换取时间;
- 我们在设计表的过程中不能完全按照范式化的要求进行设计,要考虑以后如何使用表;有的时候,范式化设计需要关联几个表才能查询到需要的数据;但是进行反范式化设计时能一张表就能查询到所需要的数据,极大的节省了性能;
-
范式化设计的优缺点
-
优点:
- 可以尽量的减少数据冗余,数据表更新快,体积小;
- 范式化的更新操作比反范式化更快;
- 范式化的表通常比反范式化更小;
-
缺点:
- 对于 查询需要对多个表进行关联
- 更难进行索引优化;
-
-
反范式化的优缺点
-
优点:
- 可以减少表的关联
- 可以更好的进行索引优化
-
缺点:
- 存在数据冗余及数据维护异常;
- 对数据的修改需要更多的成本;(比如一条记录更新了,但是其他地方也有此字段,也需要进行整体更新;)
-
4.3 物理设计
-
物理设计涉及的内容
- 定义数据库、表ji字段的命名规范
- 选择合适的存储引擎
- 为表中的字段选择合适的数据类型
- 建立数据库结构;
-
定义数据库、表及字段的命名规范
- 数据库、表及字段的命名要遵守可读性规则;
- 数据库、表及字段的命名要遵守表意性原则
- 数据库、表及字段的命名要遵守长名原则;
-
选择合适的存储引擎
存储引擎 | 事务 | 锁粒度 | 主要应用 | 忌用 |
---|---|---|---|---|
MyISAM | 不支持 | 支持并发插入的表级锁 | SELECT,INSERT | 读写操作频繁 |
MRG | 不支持 | 支持并发插入的表级锁 | 分段归档,数据仓库 | 全局查找过多的场景 |
Innodb | 支持 | 支持MVCC的行级锁 | 事务处理 | 无 |
Archive | 不支持 | 行级锁 | 日志记录,只支持insert,select | 需要随机读取,更新,删除 |
Ndb cluster | 支持 | 行级锁 | 高可用性 | 大部分应用; |
Archive适合日志等存储,因为它不可修改。
4.4 数据类型的选择
- 为表中的字段选择合适的数字类型
- 当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制类型,最后是字符类型。对于相同级别的数据类型,应该优先选择占用空间小的数据类型。
- 如何正确的选择整数类型:
- 如何正确的选择实数类型:
- 如何选择VACHAR和CHAR类型
- VARCHAR类型的存储特点:
- varchar用于存储长字符串,只占用必要的存储空间
- 列的最大长度小于255则只占用一个额外字节用于记录字符串长度
- 列的最大长度大于255则要占用两个额外字节用于记录字符串长度
- VARCHAR长度的选择问题
- 使用最小的符合需求的长度
- varchar(5)和varchar(200)存储MySQL字符串性能不同(定长了可能会更多的消耗内存)
- VARCHAR的适用场景:
- 字符串列的最大长度比平均长度大很多
- 字符串列很少被更新
- 使用了多字节字符集存储字符串
- CHAR类型的特点:
- CHAR类型是定长的
- 字符串存储在CHAR类型的列中会删除末尾的空格
- CHAR类型的最大宽度为255
- CHAR类型的适用场景:
- CHAR类型适合存储所长度近似的值
- CHAR类型适合存储短字符串
- CHAR类型适合存储经常更新的字符串列
- VARCHAR类型的存储特点:
4.5 如何存储日期类型
- 如何存储日期数据:
timestamp类型显示依赖于所指定的时区,在时区修改时可以自动修改timestamp列的值
- date类型和time类型
- 把日期部分存储为字符串(至少要8个字)
- 使用int类型来存储(4个字节)
- 使用datetime类型来存储(8个字节)
- date类型的优点:
- 占用的字节数比使用字符串、datetime、int存储要少,使用date类型只需要3个字节
- 使用Date类型还可以利用日期时间函数进行日期之间的计算
- date类型用于保存1000-01-01到9999-12-31之间的日期
- time类型用于存储时间数据,格式为HH:MM:SS
- 存储日期时间数据的注意事项:
- 不要使用字符串类型来存储日期时间数据(日期时间类型通常比字符串占用的空间小、在进行查找过滤时可以利用日期来进行对比,还有着丰富的处理函数,可以方便的对日期类型进行日期计算)
- 使用Int存储日期时间不如使用Timestamp类型
4.6 物理设计总结
- 一个物理设计主要由以下组成:
- 建议使用innodb作为存储引擎:
- 为表中每个列选择合适的类型
- 如何选择表的主键
- 主键应该尽可能的小
- 主键应该是顺序增长的
- 增加数据的插入效率
- Innodb的主键和业务主键可以不同
- 数据库结构:
- 查询性能要求
- 范式化要求
以这两点为核心
五. MySQL高可用架构设计
5.1 mysql复制功能介绍
- 由于mysql的事务功能导致我们不能简单的通过增加服务器数量来分担读写负载;但是我们可以通过复制功能来解决读负载
- 复制解决了什么问题:
- 实现在不同服务器上的数据分布(利用二进制日志增量进行,不需要太多的带宽,但是使用基于行的复制在进行大批量的更改时,会对带宽带来一定的压力,特别是跨IDC环境下进行复制,应该分批进行)
- 实现数据读取的负载均衡(需要其他组件配合完成,利用DNS轮询的方式把程序的读连接到不同的备份数据库,使用LVS,haproxy这样的代理方式;
- 增强了数据的安全性(利用备库的备份来减少主库负载,但是复制并不能代替备份,因为主库如果删除了某些数据,从库会跟着删除,所以要想恢复删除的数据还是得需要备份)
- 实现了数据库高可用和故障切换
- 实现数据库在线升级(用一个高版本的数据库作为主库或者备库,或者进行测试)