数据库性能与容量评估
参考:
https://www.cnblogs.com/zhangfengshi/p/11665486.html
https://www.cnblogs.com/Aiapple/p/5697912.html
https://blog.csdn.net/capsicum29/article/details/71480799
https://www.cnblogs.com/zping/p/8874301.html
数据库分库分表容量划分建议参考阿里云DRDS原则
做分库分表的时候 一直想知道分库分表容量的最优规则有什么好的建议,以下是参考阿里云 DRDS 分库分表的规则,还是有一定的参考意义 。
mysql 性能容量评估
- 分析上线业务场景
- 评估数据库服务器所需性能指标
- 预估可能成为瓶颈的服务器资源
- 帮助数据库性能调优
- 磁盘IO性能
- 内存容量
- CPU
- 网络吞吐量
- 磁盘容量
- OLTP/OLAP
- 并发请求
- 读写比例
- 数据量
- 冷热数据比
- 数据分级存储
- 业务高峰时数据库的每秒并发访问量是多少
- 通过应用服务器数量,连接池配置判断
- 通过产品估算初上线用户规模和用户增长速度判断
- 通过实际业务业务类型判断
- 并发量相关资源:cpu
- 线上业务select只读与update/delete/insert写操作比例
- delete/update通常都是先读再写
- insert需要区分数据写入还是持续insert还是大量导入数据
- 根据业务实际场景分析
- 数据库服务器存储设备可扩容能力的上限
- 根据估算的业务量,写入模式,分析数据增长量
- 预计一个硬件升级周期内数据库可存放数据的总量,上线时要留好余量
- 数据总量相关资源:磁盘容量
- 热数据,线上最新一定周期内将被反复访问的数据
- 冷数据,线上保存着的,最近不会被在线用户用到的数据
- 估算活跃用户量,数据增长量等预估热数据量
- 内存大小尽可足够存放线上实时热数据
- 热数据相关资源:内存
- OLTP/OLAP
- 并发请求
- 读写比例
- 数据量
- 冷热数据比
- 数据分级存储
- 用于存放线上数千万歌曲信息
- 确定属于OLTP线上类型数据库
- 并发请求
-
- 50台应用服务器,每台最大连接数100
- 可能峰值5000qps,并发请求量较大
- 所以:CPU需求高
- 读写比例
-
- 访问模式以用户列出歌单和播放歌曲时查询歌曲信息为主,用户只有只读查询
- 写数据发生在录入新歌或修改歌曲信息时后台操作,写比例小,且为批量导入
- 读写比例:100:1
- 数据总量
-
- 估算每首歌信息8K,总计5000万,总量400G
- 数据总量增长相对较慢
- 冷热数据比
-
- 5000万歌曲中大约40%可能被访问,10%属于热点歌曲
- 热数据大约<40G
- 数据分级存储需求
-
- 由于没有用户产生的数据,歌曲信息无法分级存储
- 并发请求高-----------------------CPU性能要求高
- 读占大部分,且热数据大约40G---内存需求一般>40G
- 数据总量400G--------------------磁盘空间需求一般>400G
- 写比例较少,且是后台批量--------磁盘IO能力需求一般
- 网络流量要求:8K*2500(每秒2500首放回给用户)/1024≈20MB/S,一般
- OLTP/OLAP
- 并发请求
- 读写比例
- 数据量
- 冷热数据比
- 数据分级存储
- 用于存放理财用户线上订单
- 确定属于OLTP线上类型数据库
- 业务场景有明显特征
-
- 特定高息产品秒杀销售时间窗有大量并发订单写入
- 平时只有少量订单查询请求,和较低的常规产品购买请求
- 评估应以满足最关键的业务高峰为基准
- 确定属于OLTP线上类型数据库
- 并发请求量
-
- 秒杀期间持续时间短,但是并发量预估30台应用服务器约2000tps(实际估算,比如限售3亿,平均每笔订单1万,则会有3万笔订单,根据实际情况,3万笔订单将在十几秒卖光,所以,每秒应该有2000笔订单完成)
- 所以CPU要求较高
- 所以网络要求较高
- 读写比例
-
- 高峰时写订单是主要开销操作
- 所以磁盘IO要求很高
- 数据总量
-
- 根据业务分析,订单属于写入瞬时量大,总量较小,单笔金额较高
- 总量预估一年成交百万单位级别,增长量较稳定
- 判断数据存储需求小于200G
- 所以磁盘空间需求一般,>200G
- 冷热数据
-
- 峰值写入为主,内存要求存放热点期间产生的脏数据即可
- 总共有3万笔订单数据产生,算一算脏数据<10G
- 数据分级存储需求
-
- 用户订单业务约定页面展示最近半年订单,半年前的需要到历史查询页面专门查询
- 因此可以做分级存储,迁移所有半年前订单至历史库
- 硬件性能指标:
-
- 磁盘IO性能
-
- 单盘->盘阵
- SAS-SATA,
- 机械盘->ssd
- 内存 较小->较大,
- cup
-
- 普通->多核,
- 超线程,
- 磁盘容量
-
- 单盘->盘阵,
- 单盘->LVM,
- 网络吞吐量
-
- 千兆->万兆,
- 单网卡->多路;
- 数据库业务特点:
-
- OLTP/OLAPM,
- 并发请求------cpu,
- 读写比例
-
- 读---内存
- 写磁盘IO,
- 数据量--磁盘容量,
- 冷热数据比
-
- 热数据多--内存,
- 数据分级存储--缓解线上磁盘空间压力
- 性能与成本的平衡
正确评估SQL数据库性能,你必须知道的原理和方法
基本概念
性能问题
什么是性能问题?当系统出现性能问题,那么反过来问为什么说出现了性能问题,或者说到底怎么样算性能问题呢?
- CPU100%,CPU占有率过高?CPU就算是100%,但是客户端反馈超快,算不算性能问题呢?
- 剩余内存过低?操作系统剩余内存过低有可能是SQL吃完了,所以不一定。那如何知道SQL使用的内存情况呢?
- 查询慢?查询慢,是否就是性能问题?如果一段存储过程写了500行,里面关联几十个表,有复杂的逻辑运算,执行一次超过3000ms,这是慢还是快呢?所以所谓的查询慢,也要有评估机制。
- 查询链接超时?查询超时,链接超时就更复杂了,有n多因素影响。
- …………
还有很多情况,客户都说性能问题。所以到底什么算性能问题呢?我个人认为是:
分为2种情况,第一是新系统运行与经验系统相差巨大,性能测试和压力测试不符合预期。第二种是正常运行系统发生与通常情况反映不一致状态,导致业务运行困难。
通常性能下降是我们说的性能问题,但是:
还有性能突然提升,比如平常打开页面3秒钟,突然什么都没有做变成了0.5秒。算不算性能问题呢?我认为也算性能问题,世界上绝对没有无缘无故的爱,也没有无缘无故的恨。所以突然的提升一定隐藏着更为重要的问题!
那么既然有了概念,有哪些关键指标来评估数据性能问题呢?有了指标,我们就需要收集指标,所以有昨天的文章。
衡量性能问题的关键指标
响应时间(Response Time)
响应时间一般指的是一条SQL 语句执行后得出结果耗费的时间。
而一般用户使用来说,比如BS结构,响应时间大家一般会认为是访问页面到页面呈现结束,这样的感官时间。这个时间就需要考虑更多的因素。比如网络、浏览器等等。曾经我碰到的CASE 页面打开速度超慢,但是数据库正常,后来分析发现是页面中潜入的一个很小的GIF影响了。所以要系统来分析。
而执行SQL语句获得的响应时间是最为纯粹的反馈,也是能够得到准备信息的步骤。
在系统跟踪的话,可以用SQL profile 来跟踪响应的内容,分析语句的反馈时间,之后再来详细讲解。
吞吐量(Thougput)
吞吐量是反映系统到底有多繁忙的指标,了解此指标可以更为清晰的知晓系统的使用状况。
性能监视器中可以用SQL Batch Request/Sec,SQL Transactions /Sec等指标来获取。
基线 (BaseLine)
BaseLine一直是我强调的指标。
基线是反映系统日常状况的指标,如果知晓了系统的各种基线值。那么就清楚了底在哪里,天在哪里。这样才能更容易去判断和解决问题。 而基线值是靠长期经验和数据获取的。
瓶颈(bottleneck)
系统一旦产生了瓶颈,我们就要去判断瓶颈,而瓶颈一般来说多会有关联性。比如内存不足可能导致IO过高,IO过高也可能导致CPU等待。
所以准确的知道瓶颈在哪里,这是需要去判断的。使用性能监视器和分析功能可以快捷的帮助大家分析瓶颈。
调优本质
调优的本质来讲,一般的调优都指的是性能出现过高,需要系统稳定的情况。所以本质来讲是干以下事情:
降低工作负载
- 减少查询请求的数量:去除不必要的数据库访问
- 降低查询请求的复杂度:优化查询逻辑的设计
- 减少查询请求之间的依赖关系:优化事务的设计和并发性控制
优化系统资源的配置
- 找出系统资源瓶颈,增加相应的资源
- 优化系统资源的分配
性能优化的方法学
如下图,性能优化涉及的层面有:
- 构架设计
- 查询优化
- 索引优化
- 并发控制
- 存储优化
- 服务器优化
相关优化的成效和收益还要顺序,可见下图:
优化的平衡
- 优化是一个持续的过程,永无止境,解决了当前“最大”的瓶颈后,下一个“最大”的瓶颈又会出现
要知道何时停止优化 - 优化的内容应该是基于业务需求的优化
- 关注二投资回报率(ROI) ,工程师的时间也是投入,因此要懂得投资回报,需要懂得停止优化!
- 改变选项是最有意义的优化策略,有的优化是业务决定,那么无法改变的时候是否可以改变业务逻辑。
- 实际上,足够好的性能就足够了。很多时候足够即可,而不是去寻找极限!
调优思路
调优思路来说,从理论上,在数据库构架时候就应该介入。但是通常我们遇到的情况都是半路出来。发生问题才找到DBA。所以遵循的思路可以是如下:
理解瓶颈,知道发生了什么,然后做优化配置,调整执行慢的语句。
然后再反复,反复。
总结
调优是个系统工程,要有敏锐的触觉,有可能一条参数改变整个系统感受。所以深入理解原理和方法,才能得心应手。 具体的方法,工具等敬请期待新的Blog。
MySQL准入规范及容量评估
一、数据库设计
1、表结构设计
-表中的自增列(auto_increment属性)推荐使用bigint类型 -首选使用非空的唯一键, 其次选择自增列或发号器 不使用更新频繁的列,尽量不选择字符串列,不使用UUID MD5 HASH -业务中选择性很少的状态status、类型type等字段推荐使用tinytint或者smallint类型 -业务中IP地址字段推荐使用int类型 -业务活跃的大表中必须有行数据的创建时间字段create_time和最后更新时间字段update_time -表中所有字段必须都是NOT NULL属性,业务可以根据需要定义DEFAULT值 -用decimal存储精确浮点数(不要用浮点类型) -不推荐使用enum,set,blob,text等类型,对于大表必须将text、blob等类型字段拆分或者独立建表
2、索引设计
-避免冗余索引 :避免将同一个字段都建立索引,索引的建立需要根据访问的SQL语句来评估 -一次查询,一个表只能用到一个索引,不要对每个查询条件的字段都单独建立索引 -单张表索引数量不超过7,单个索引字段数不超过5 -不在null列上加索引 -不在低基数列上建立索引,例如“性别” -复合索引字段排序,区分度最大的字段放在前面 -核心SQL优先考虑覆盖索引 -对字符串使用前缀索引 -前缀长度不超过8个字符 ,必须是最左前缀
3、字符集及校验集
-数据库和表的字符集必须一致,且所有表的字符集必须一致,只能是utf8;数据库中所有表采用统一的校验集 -主、从数据库的字符集必须一致 -前端程序字符集或者环境变量中的字符集,与数据库、表的字符集必须一致
4、其他要求
-不推荐使用外键,临时表,视图,自定义函数,存储过程以及触发器 -SSD硬盘上,单表数据行数不能超过5000万或者存储空间不得大于30GB -SAS硬盘上,单表数据行数不能超过2000万或者存储空间不得大于15GB -上线前DBA必须根据1年内的业务访问量和数据增长量,给出库、表的扩展方案
二、SQL编写
1、select
-SELECT语句必须指定具体字段名称,禁止写成“select *” -SELECT语句禁止使用UNION,推荐使用UNION ALL,并且UNION子句个数限制在5个以内
2、DML
-INSERT语句必须指定具体的字段名称,不要写成INSERT VALUES(……)形式 -SQL语句在程序中传入的参数值类型必须与字段在数据库中的类型相同
3、多表联合查询
-多表连接查询推荐使用别名,且SELECT列表中要用别名引用字段,数据库.表格式,如“select a.cid from iknow_qb. tblreply a where …” -生产系统中,单个查询中不推荐将3张表以上(包括3张表)做连接 -生产系统中,强烈不推荐使用外关联,包括左外关联,右外关联和全外关联 -在多表连接的查询中,驱动表须要选择结果集较小的表 -禁止写成多层子查询嵌套的SQL语句,推荐改写成表顺序连接的格式 -尽量不要在INSERT|UPDATE|DELETE|REPLACE语句中进行多表连接操作
4、事务
-事务中INSERT|UPDATE|DELETE|REPLACE语句操作的行数控制在2000,以及WHERE子句中IN列表的传参个数控制在2000 -批量操作数据时,需要控制事务处理间隔时间,进行必要的sleep,具体值由DBA给出,并且程序必须有中断处理能力 -对于有auto_increment属性字段的表的插入操作,并发需要控制在200/s以内 -SQL级别/事务级别/主从数据库中的表存储引擎类型要一致,存储引擎混合使用会导致主从数据不一致或主从同步中断 -对于同步延迟不敏感的只读查询,必须放到从库上执行;对于同步延迟敏感的只读查询,可以放到主库上执行 -前端程序中尽量不要使用set语句,包括set names、set sql_mode和set isolation_level等
5、表扫描方式:
-SELECT|UPDATE|DELETE|REPLACE要有WHERE子句,且WHERE子句的条件必需使用索引查找 -生产数据库中强烈不推荐大表上发生全表扫描,但对于5000行以下的静态表可以全表扫描 -业务中大表全表扫描和全表导出(dump)推荐放在备份库或者线下读库中进行 -WHERE 子句中禁止只使用全模糊的LIKE条件进行查找(如like '%aj%'),必须有其他查询条件 -WHERE子句中的索引列或组合索引前导列上不能使用函数
6、排序和分组
-有distinct、order by和group by子句的查询,中间结果集限制10000行以内 -对于大结果集(中间结果集超过10000行)的排序、分组放到程序端实现
7、其他要求
-单个SQL语句的大小限制在5MB以内 -生产数据库中SQL语句的中间结果集和最终结果集必须限制在5MB以内 -生产数据库中SQL语句禁止使用提示,如force index,ignore index,straight_join,sql_no_cache等 -禁止使用全文检索功能 -禁止使用事件(EVENT)功能 -程序中不要使用或操作mysql库和test库,禁止创建test或以test开头的库 -禁止在mysql中使用用户自定义变量 -线上数据库中不要进行业务的实时统计或者汇总等计算操作,可导出后利用其它工具或者在线下备份库中完成 -减少与数据库的交互次数 INSERT ... ON DUPLICATE KEY UPDATE REPLACE INTO、INSERT IGNORE 、INSERT INTO VALUES(),(),() UPDATE … WHERE ID IN(A,B,C,…) -不使用负向查询,例如 not in,!= ,not like -不在索引列进行数学运算和函数运算 -不使用%前导的查询,例如like “%abc” -避免大表数据类型间的隐式转换(这个经常出性能问题)会导致索引失效,例如数字转字符串
三、MySQL相关特点介绍
1、MySQL对SQL的处理特点
-SQL请求处理只能使用一个核 -没有SQL编译缓存,SQL存储过程都是硬解析 -索引上不支持运算对比 -大多情况下一个Query只能使用一个索引 -不支持Hash jion(MariaDB目前支持) -基于线程的对外服务模型(连接数太高,性能下降严重) -子查询支持较差,外层查询一般走不了索引
2、MySQL支持的存储大小
-单个表空间64T, 每个表只有一个表空间,也就是每个单表最大64T -Innodb Logfile 加起来不能超过512G -每行大小限制65535 byte -每个表最多1027个字段 -每个表最多64个普通索引
3、MySQL生产参考指标
-单实例最好不要超过1T, 周边LOG除外,最大不建议超过5T -一般的OLTP单表建议最大不要超过10G -通常在有buffer命中的情况下: Select 可以达到3-6W/S Insert 在聚集索引连续的情况可以到2w-3W/S 在聚集索引不连续的情况下有可能也就是200-300/S UPDATE数据在内存的情况下可以达到3K/S DELETE数据在内存的情况下可以达到1k/s,有可能更少 -数据库的瓶颈: IO能力 ,想办法用顺序IO,减少随机IO
四、建表审核
五、容量评估
1、容量评估概述
所有的数据库上线:新建集群、新建数据库、新建表,都需要提前进行容量评估,防止后续因容量问题而又对已上线的业务进行调整、扩容、迁移等操作,从而对线上业务造成影响。容量包括:访问量(读写)、数据及增长量、磁盘空间容量.
2、表容量
表容量主要从表的记录数、平均长度、增长量、读写量、总大小量进行评估。一般对于OLTP的表,建议单表不要超过2000W行数据量,总大小15G以内。访问量:单表读写量在1600/s以内。
对于单表数据量上百万的表,每行记录长度不要过长,不要和text、blob等字段类型放在同一个表中。(MySQL数据页大小为16K,每行记录越长,每个数据页存储的记录数就越少,因此在对数据进行检索时,会产生更多的IO)
3、实例容量
MySQL是基于线程的服务模型,因此在一些并发较高的场景下,单实例并不能充分利用服务器的CPU资源,吞吐量反而会卡在mysql层,特别是对于mysql5.5版本。在mysql 5.6版本中 做了很大优化,而且percona 版本有thread pool ,可以充分应对高并发场景下CPU上下文切换消耗过高的问题。
单实例QPS吞吐量一般控制在20000/s以内,写入量还需考虑从库延迟问题,对于mysql5.6版本可以考虑进行分库后再分表,充分利用5.6版本基于库级别的多线程复制,从而提高写入的吞吐量。
4、磁盘空间
服务器一般会承载多个数据库实例,因此在各个实例上线前,需要对各个实例进行 数据量的评估,以及1-2年内 主要的几个大表的增长量情况,对数据量的评估,尽量精确到每个字段。对于增长量不是特别快的业务(半年就翻倍的情况),建议1-2年的数据量,最终占磁盘使用率的70%以内。同时,对于一些数据增长较快,可以考虑使用大的慢盘进行数据归档。