热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一文总结高并发大数据量下MySQL开发规范【军规】

在互联网公司中,MySQL是使用最多的数据库,那么在并发量大、数据量大的互联网业务中,如何高效的使用MySQL才能保证服务的稳定呢?根据本人多年运维管理经验的总结,梳理了一些核心的

在互联网公司中,MySQL是使用最多的数据库,那么在并发量大、数据量大的互联网业务中,如何高效的使用MySQL才能保证服务的稳定呢?根据本人多年运维管理经验的总结,梳理了一些核心的开发规范,希望能给大家带来一些帮助。


一、基础规范

  • 数据库字符集默认使用utf8mb4,兼容utf8,并支持存储emoji表情等四字节内容
  • 禁止在线上生产环境做数据库压力测试
  • 禁止从测试、开发环境、本机直连线上生产数据库
  • 禁止在数据库中存储明文密码
  • 禁止在数据库中存储图片、文件等大数据
  • 禁止将业务日志实时保存到数据库,建议保存到日志文件,对于统计后的结果再存放到mysql中
  • 禁止线上核心业务使用mysql存储过程、视图、触发器、Event、InnoDB外键约束等,这些容易将业务逻辑和db耦合在一起,而且在MySQL的这些特性中存在严重BUG
  • 业务部门的推广活动,请提前通知dba进行服务和访问评估。


二、库表设计

  • 库名、表名、字段名必须使小写字母,并采用下划线分割;对相关功能的表应当使用相同前缀,如job_xxx,前缀通常为库名或依赖主实体对象,数据库名称约定:db_xxx
  • 数据库表默认存储引擎为InnoDB,所有环境禁止使用MyISAM、Memory等其他存储引擎
  • 所有的表及字段都必须有备注,详细说明表及字段的含义
  • 涉及货币金额或其他精度敏感的数据必须使用定点数DECIMAL替代FLOAT和DOUBLE
  • 库名、表名、字段名禁止使用MySQL保留字,如date、like、desc、return等
  • 控制表字段数,单表不超过50个纯INT/20个VARCHAR(10)字段等同存储体积的字段数,上限控制在20~50
  • 字段长度只分配真正需要的空间

问题:使用VARCHAR(5) 和VARCHAR(200) 存储’hello’的磁盘空间开销是一样的,使用更短的列有什么优势吗?

更大的定义列会消耗更多的内存,因为MySQL通常会分配固定大小的内存块来保存内部值,尤其是使用内存临时表进行排序或操作时会特别糟糕。


三、索引设计

基本规则:索引不是越多越好,能不添加的索引尽量不要添加,过多的索引会严重降低数据插入和更新的效率,并带来更多的读写冲突和死锁!

  • 索引名称必须使用小写,普通索引按照“idx_字段名_字段名[_字段名]”进行命名,唯一索引按照“uniq_字段名_字段名[_字段名]”进行命名”
  • 表必须有主键,推荐使用独立于业务的AUTO_INCREMENT列或全局ID生成器做主键,禁止使用多字段做联合主键
  • 不使用UUID/MD5/HASH等函数生成的无规则值做主键,效率极差
  • 索引数量控制
  • 单张表中索引数量不超过5个
  • 单个索引中的字段数不超过5个
  • 对字符串使用前缀索引,前缀索引长度不超过10个字符
  • 索引字段的顺序需要考虑每个字段去重之后的数量,区分度最大的【个数最多的】放在前面。
  • 合理创建联合索引(避免冗余),符合最左前缀原则:(a,b,c) 相当于 (a) 、(a,b) 、(a,b,c)
  • 可能需要添加索引的字段:
  • ORDER BY,GROUP BY,DISTINCT的字段需要添加在索引的后面
  • UPDATE、DELETE语句需要根据WHERE条件添加索引
  • 对于JOIN操作,需要在JOIN字段上建立索引
  • 线上慎用FORCE INDEX,使用前需要和DBA沟通,并得到DBA的测试允许
  • 线上OLTP系统中禁止使用外键,高并发时极易引起死锁等问题
  • 索引使用禁忌
  • 不使用%前导的查询,如like “%ab”
  • 不使用负向查询,如not in/not like/<>
  • 不在低区分度的列上建立索引,例如“性别”
  • 不在索引列进行数学运算和函数运算

示例:假设在表tab中id建立了索引

      • Select col_A,col_B from tab where id + 1 > 10001 不会使用索引
      • Select col_A,col_B from tab where id > 10001 – 1 会使用索引


四、SQL优化

  • 线上尽量少使用大SQL,可能一条大SQL就把整个数据库堵死,将复杂SQL拆分为多条简单SQL,化繁为简
  • 一条SQL只能在一个CPU上运算,如果SQL比较复杂执行效率会非常低【8.0之后开始支持单SQL多CPU核执行,但是效果有限】
  • 简单SQL缓存命中率更高
  • 减少锁表时间
  • 充分利用多核CPU,提高并发效率
  • 减少MySQL端的数学运算和逻辑判断,避免SQL语句出现md5()、order by rand()等
  • 尽量少用SELECT * ,只取需要的数据列, 避免无谓的IO、CPU和网络开销
  • WHERE条件中,同一字段改写OR为IN(),IN包含的值不应过多,默认不超过200个,IN里禁止使用子查询
  • 过滤表记录合并且不去重的情况,改写UNION为UNION ALL
  • 减少使用拼接SQL,使用预编译语句,降低SQL注入概率
  • WHERE条件中的非等值条件(IN、BETWEEN、<、<=、>、>=)会导致使用不了联合索引的后续字段,注意避免
  • WHERE条件比较,字段类型和传入值必须保证类型一致,避免隐式转换

示例:

字段: code varchar(50) NOT NULL COMENT ‘编码’ #code上建立了索引

SELECT id,name,addr from tab_name where code=10001; 不会使用索引

SELECT id,name,addr from tab_name where code='10001'; 会使用索引

  • Limit分页优化
  • 传统分页:

Select * from table limit 10000,10;

LIMIT原理:

Limit 10000,10 偏移量越大则越慢

  • 推荐分页:
  • 分页方式一:

Select * from table WHERE id>=23423 limit 11; #10+1 (每页10条)

Select * from table WHERE id>=23434 limit 11;

  • 分页方式二:

Select * from table WHERE id >= ( select id from table limit 10000,1 ) limit 10;

  • 分页方式三:

Select * from table INNER JOIN (SELECT id from table limit 10000,10) USING(id)

  • 分页方式四:

        • 程序取ID: Select id from table limit 10000,10;
        • Select * from table WHERE ID in(123,456…);

最后说明:

上述规范是多年MySQL数据库使用的经验总结,希望能给大家带来一些启发和帮助!

如果你还想看更多优质原创文章,欢迎关注我的公众号「数据库架构师」,提升数据库技能。


推荐阅读
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
  • 本文详细介绍了Oracle 11g中的创建表空间的方法,以及如何设置客户端和服务端的基本配置,包括用户管理、环境变量配置等。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • CentOS下ProFTPD的安装与配置指南
    本文详细介绍在CentOS操作系统上安装和配置ProFTPD服务的方法,包括基本配置、安全设置及高级功能的启用。 ... [详细]
  • 如何从BAM文件绘制ATAC-seq插入片段长度分布图?
    在ATAC-seq数据处理中,插入片段长度的分布图是一个重要的质量控制指标,它能反映出核小体的周期性排列。本文将详细介绍如何从BAM文件中提取并绘制这些数据。 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文探讨了在Windows系统中运行Apache服务器时频繁出现崩溃的问题,并提供了多种可能的解决方案和建议。错误日志显示多个子进程因达到最大请求限制而退出。 ... [详细]
  • java类名的作用_java下Class.forName的作用是什么,为什么要使用它?
    湖上湖返回与带有给定字符串名的类或接口相关联的Class对象。调用此方法等效于:Class.forName(className,true,currentLoader) ... [详细]
  • flea,frame,db,使用,之 ... [详细]
  • 在编程实践中,正确管理和释放资源是非常重要的。本文将探讨 Python 中的 'with' 关键字及其背后的上下文管理器机制,以及它们如何帮助我们更安全、高效地管理资源。 ... [详细]
  • 本文详细介绍了C++中的构造函数,包括其定义、特点以及如何通过构造函数进行对象的初始化。此外,还探讨了转换构造函数的概念及其在不同情境下的应用,以及如何避免不必要的隐式类型转换。 ... [详细]
author-avatar
钓鱼翁玩围脖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有