第一章 MySQL业务优化与设计

第二节 MySQL数据库设计

  • 什么是schema设计
    schema设计是指设计数据库的表、索引以及表与表之间的关系。
    • 在数据建模的基础之上将关系模型转换为数据库表
    • 满足业务模型的基础之上根据数据库和业务特点优化表结构
      MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 为什么schema需要设计
  • schema关系到应用程序功能与性能
    • 满足业务功能需要
    • 同性能密切相关
    • 数据库扩展性
    • 满足周边需求(统计、数据迁移等)
  • 关系模型数据库修改schema通常是高危操作
    • schema设计要体现一定的前瞻性
  • 完全由开发者主导的schema设计
    • 着眼于实现当前的功能
    • 完全基于功能的设计可能存在一些隐患
      • 不合理的表结构或索引造成性能问题
      • 没有合理的评估到数据量的增长造成空间紧张造成难以维护
      • 需求频繁修改造成表结构经常变更
      • 业务重大调整导致数据经常要重构订正
  • 基于性能的数据库设计

  • 根据查询需要设计好索引

  • 根据核查查询需求,适当调整调结构

  • 针对一些特殊需求,调整实现方式

  • 索引

  • 正确的使用索引

  • 更新尽可能使用主键或唯一索引

  • 主键尽可能使用自增字段ID字段

  • 核心查询覆盖扫描

  • 反范式,冗余必要字段

  • 针对核心SQL,保留查询结果所必须的必要字段,避免频繁的join

例:消息表中冗余每次读消息必须要反馈的nickname字段,避免每次读消息都变成join操作,代价是用户修改nickname代价变高。
MySQL学习记录04-MySQL应用于优化之MySQL数据库设计

  • 拆分大字段
  • 拆分大字段到单独表当中,避免范围扫描代价大

例:博文拆分成两份,标题表只保留标题和内容缩率部分,用于快速批量返回消息列表,正文表保留大段博文内容,用于点开文章单个读取。
MySQL学习记录04-MySQL应用于优化之MySQL数据库设计

  • 避免过多字段或过长行
    • 根据SQL 必要返回设计字段,有必要就拆表,避免过多字段
    • 一次没必要获取那么多列数据
    • 行过长避免数据页记录,范围扫描性能变低
    • 更新数据页代价增加
    • 16K页最少放2行,可能出现行迁移
  • 分页查询
    • 避免limit,offset过大
    • 应该使用自增主键ID模拟分页
      1.直接查
      2.得到第一页的max(id)=123
      3.第二页,带上id>123查询:where id>123 limit=100
    • 这样每次只需扫描100行数据
  • 要求业务上禁止XX页之后的数据查询
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 热点读数据特殊处理
  • 根据数据读取频率或数量不同对数据做特殊处理
    • 例:论坛系统中置顶帖、公告帖,可以单独拆分存储,由于每次访问都要读出来,单独放出来,避免每次都要到普不同表中随机找出来。
      MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 热点写数据特殊处理
  • 根据数据获取的频率和数量不同对热点数据做特殊处理
    - 例:微博系统中对大量人关注的热点账号消息从“推”改为“拉”,避免过量insert操作。
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 准实时统计
  • 对不需要精确结果的计数等统计要求,建立定期更新结果表
    - 例:首页要求展示动态成交总金额,维护一个计数表,每分钟根据原表注册时间获取增量sum值更新计数表,避免每次用户刷新都要扫描交易全记录表
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 实时统计改进1-触发器实时统计
  • 对需要精确统计的技术利用数据库触发器维护计数表
    - 例:用户量冲亿活动要去实时统计,在用户表添加触发器,每次有新用户插入就同时在计数器+1
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 实时统计改进2-缓存实现实时统计
  • 对需要精确统计的计数利用前端缓存实时维护计数
    • 例:用户量冲亿活动要求实时统计,注册数量在缓存中实时维护,每注册一个就+1,完全避免数据库读写操作,缓存万一故障失效,可从数据库整体count重新获取到缓存中。
      MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 实时统计改进3:最大自增ID获取总数
  • 很多逻辑可以利用自增ID主键最大值直接作为总数
    • 例:用户量冲亿活动要求实时统计,用户表加上自增ID作为主键,只要取当时max(ID)就可以得到用户总数
      MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 可扩展性设计
  • 可扩展性
    • 硬件资源增长有极限的情况下处理尽可能久的线上业务
  • 数据分级,冷数据归档与淘汰
    • 可以不断释放空间供新数据使用
  • 为数据分布式准备
    • 分库分表
    • 水平拆分
    • 牺牲一定的关系模型支持
  • 分区表与数据淘汰
  • range分区
  • 适合数据需要定期过期的大表
  • 单个分区扫描迁移数据到历史库避免全表扫描IO开销
  • 扇区单个分区非常高效
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 分区表与垂直分区
  • list分区
  • 适合将来可能要基于地区、类目等方式垂直拆分的数据的方式
  • 清理节电上不要的数据非常高效
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 分区表与水平分区
  • hash分区
  • 适合将来需要做水平拆分的表
  • 清理节点上不要的数据非常高效
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • MySQL分区表的局限性
  • 主键或唯一键必须包含在分区字段内
  • 分区字段必须是整数类型,或者加上返回整数的函数
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • 满足周边需求
  • 为周边需求额外增加表设计
  • 为后台统计任务增加特殊索引
  • 为数据迁移或统计需求增加时间戳
  • 统计和后台需求
  • 统计运行SQL往往和线上有很大不同
    • 利用MySQL一主多从,主从可以建不同索引的特性将统计分流到特定从库
    • 包括一些特殊用户批量查询等,所有对线上有IO压力的查询都要读写分离
  • 自动更新时间戳
  • 统计需求经常要求从上线读走增量数据
  • 表的第一个timestamp类型字段在写入时如果不填值,会自动写入系统时间戳
  • 标的第一个timestamp类型字段每次记录发生更新后悔自动更新
  • update_time字段上建索引引用于定时导出增量数据
    MySQL学习记录04-MySQL应用于优化之MySQL数据库设计
  • schema设计与前瞻性
  • 基于历史经验教训,预防和解决同类问题
  • 把折腾DBA够呛的所有schema改造的原因记录并分析总结
    • 例:业务为了用户信息加密做了大改造
      • 数据库结果大量流动,增加了加密字段,验证策略表,所有表重新订正数据等等
      • 是否所有用到用户信息管理的应用都要去上线就用密文
        例:程序BUG误删数据,线上风险大
      • 改造业务流程,不再删除数据,加入is_deleted标记位
      • 今后的类似表是否一上线就都用标记位的方式,并加上修改原有。
  • 支付类应用后期做了风险改造
    - 对线上订单大表改造,加了限额、终端类型等字段
    - 遇到支付类应用,是否已上线就提示业务是否需要考虑风控并留好相关字段

相关文章:

  • 2022-12-23
  • 2021-07-02
  • 2021-03-30
  • 2022-01-18
  • 2021-09-06
  • 2021-12-05
  • 2021-12-03
猜你喜欢
  • 2021-04-25
  • 2022-12-23
  • 2021-06-18
  • 2022-02-11
  • 2021-09-02
  • 2021-05-20
  • 2021-12-08
相关资源
相似解决方案