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

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

时间:2023-06-28 09:22:22浏览次数:50  
标签:10 SQL 使用 索引 数据量 军规 MySQL id Select

在互联网公司中,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…);

标签:10,SQL,使用,索引,数据量,军规,MySQL,id,Select
From: https://www.cnblogs.com/jelly12345/p/17510487.html

相关文章

  • #yyds干货盘点#线上MySQL的自增id用尽处理
    MySQL的自增id都定义了初始值,然后不断加步长。虽然自然数没有上限,但定义了表示这个数的字节长度,计算机存储就有上限。比如,无符号整型(unsignedint)是4个字节,上限就是2^32-1。那自增id用完,会怎么样?表定义自增值id表定义的自增值达到上限后的逻辑是:再申请下一个id时,得到的值保持不......
  • mysql常用命令
    连接到MySQL服务器:mysql-uusername-p显示数据库列表:SHOWDATABASES;创建数据库:CREATEDATABASEdatabase_name;删除数据库 USEdatabase_name;DROPDATABASEdatabase_name;  切换到指定数据库:USEdatabase_n......
  • mysql MHA
    一:主从复制作用和缺点2.MHA的作用特点3.MHA节点的类型 本文用到的软件包在以下链接中https://pan.baidu.com/s/11ikNZ5sJcXRJA3sRMfUfaA?pwd=lomn使用的系统版本为centos7.4版本,mysql版本为8.0.32,本文使用四台centos7.4虚拟机安装mysql不再赘述,可翻阅博主以前的博客二:创建主从复制......
  • MySQL安装与卸载
    MySQL安装下载地址官网下载地址:https://dev.mysql.com/downloads/mysql/解压安装包将安装包解压(尽量解压在没有空格没有中文的目录下)##配置MySQL此电脑->属性->高级系统设置->环境变量在系统环境变量中新建变量名为:MYSQL_HOME的变量,变量值为MySQL的解压目录在......
  • 基于MySQL+SpringBoot+IDEA开放的绩效评估系统
    基于MySQL+SpringBoot+IDEA开放的绩效评估系统项目介绍......
  • mysql优化原则
    1.尽量不要在列上运算,这样会导致索引失效例如:select*fromadminwhereyear(admin_time)>2014优化为:select*fromadminwhereadmin_time>'2014-01-01′2.limit的基数比较大时,使用betweenand代替例如:select*fromadminorderbyadmin_idlimit100000,10优化为:se......
  • MySQL参数max_connect_errors分析释疑
    最近一MySQL服务器,由于一些特殊因素遇到“ERROR1129(00000):Host'xxx'isblockedbecauseofmanyconnectionerrors.Unblockwith'mysqladminflush-hosts'”,在问题解决后,在详细了解参数max_connect_errors的过程中,有些不同网络资料的矛盾描述确实让我有点迷惑和混淆(关......
  • MySQL主从复制参考
    https://blog.csdn.net/qq_52061700/article/details/126979017https://www.jb51.net/article/180748.htm相关执行命令:mysqldump-uroot-p密码--opt-R数据库名称>/opt/app/bak.sql;--主数据库备份,用来导入从数据库,保证两边数据一致CREATEUSERcopyoperatorIDENTIFI......
  • mysql中如何查看表是否被锁
    如何查看是否发生死锁在使用mysql的时候,如何查看表是否被锁呢?查看表被锁状态和结束死锁步骤:1.在mysql命令行执行sql语句usedbName;//切换到具体数据库showengineinnodbstatus;//查询db是否发生死锁12 2.查看数据表被锁状态showOPENTABLESwhereIn_use>0......
  • docker compose 配置 mysql 容器启动时创建数据库
    要在DockerCompose中配置MySQL容器,在容器启动时创建数据库,你可以按照以下步骤进行操作:在你的DockerCompose文件中,定义一个MySQL服务。确保你已经设置了适当的环境变量,如MYSQL_ROOT_PASSWORD和MYSQL_DATABASE。下面是一个示例的DockerCompose配置:version:'3'......