MySQL模式开发设计规范问题与建议
wptr33 2024-11-26 09:30 22 浏览
1.时间类型的数据默认值是否可以为null?
根据反馈,时间类型的数据默认值往往在业务上无法赋予一个确定的值,而”1970-01-01“、”0000-01-01“等等的默认值在开发过程中会增加判断工作,经过新版MYSQL(版本号8.0.19)测试,为null的数据可以走索引,故开放时间类型的数据默认值的限制。
* 补充不建议为Null的技术观点:老版本MYSQL在对null值的判断上无法走索引,不能使用=,<,>这样的运算符,对null做算术运算的结果都是null,count时不会包括null行,null比空字符串都需要更多的存储空间。
2.json数据类型是否建议使用?
关于json数据类型的意义、优缺点和设计思路可以详见附件文档json部分,考虑到目前开发进度,我来针对所有作为检索列的json数据类型字段增加虚拟列以防止性能问题的产生(开发无需更改任何代码),前提需要各位老师提供对应的SQL语句或者KEY。
3.text数据类型是否建议使用?
关于text数据类型的缺点和设计思路详见附件文档text部分(text类型的基本原则是能不用就不用),否则后期优化也会产生一定工作量。
4.字段名称与数据类型不一致
比如新建表 epidemic_inout_dynamics_info 的字段 effective_time 类型为varchar(500),这种工单在我看来单从技术角度肯定是不符合规范,并且也无法从技术角度上去限制,故需要工单发起人说明下此设计的需要和目的,如无特殊需求,工单会考虑做驳回处理。
5.审核消息通知
目前运维框架平台,都采用钉钉对接的方式进行消息提醒,不必微信群里再确认,看到审核通过执行成功,就代表数据库修改完成。
MYSQL优化主要分为以下四大方面:
设计:存储引擎,字段类型,范式与逆范式
功能:索引,缓存,分区分表。
架构:主从复制,读写分离,负载均衡。
合理SQL:测试,经验。
优化与建议总结会按照【高危】、【强制】、【建议】三个级别进行标注,遵守优先级从高到低。对于不满足【高危】和【强制】两个级别的设计,DBA会强制要求修改。
名称设计
- 【强制】表和列的名称必须控制在32个字符以内,表名只能使用字母、数字和下划线,一律小写。
- 【强制】表名、字段名不应该使用数据库内定义的关键字,如:DATE、PASSWORD、VALUE、STATUS 等。
字段类型设计
bigint
【建议】占用8字节,比int类型占用空间大一倍,需要根据实际业务选择是否使用bigint,如果int类型可以满足优先使用int类型,慎用bigint类型。必须有默认值且不能为NULL,作为自增列需设置无符号标志unsigned。
UNSIGNED属性就是将数字类型无符号化,与C、C++这些程序语言中的unsigned含义相同。例如,INT的类型范围是-2 147 483 648 ~ 2 147 483 647, INT UNSIGNED的范围类型就是0 ~ 4 294 967 295。
在MYSQL中整型范围:
类型 大小 范围(有符号) 范围(无符号) 用途
TINYINT 1 字节 (-128,127) (0,255) 小整数值
SMALLINT 2 字节 (-32 768,32 767) (0,65 535) 大整数值
MEDIUMINT 3 字节 (-8 388 608,8 388 607) (0,16 777 215) 大整数值
INT或INTEGER 4 字节 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
int、smallint、tinytint
【建议】尽量使用存储空间小的数据类型,比如状态字段应选择TINYINT数据类型。业务上无负数数据要求的使用无符号的数据类型,例如交易金额字段应优先选择:MEDIUMINT ZEROFILL, 必须有默认值且不能为NULL,作为自增列需设置无符号标志unsigned。
bit
【高危】禁止使用此类型,此类型加上索引会导致查询结果错误,并且SQL审核平台前端不支持显示此类型数据。
date、time
【建议】业务上只存储年份、日期、时间的只能选择YEAR、DATE、TIME,不能使用DATETIME替代。必须 有默认值且不能为NULL。
datetime
【建议】在不能选择TIMESTAMP的业务场景才能选择DATETIME(),因为datetime占用8字节,timestamp仅占用4字节,但是范围为1970-01-01 00:00:01到2038-01-01 00:00:00。根据业务场景可以为NULL,保证有默认值且尽量不能为NULL,例如:
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'。
decimal
【强制】存储金钱的字段,建议用int,程序端乘以100和除以100进行存取。int占用四个字节,大部分情况下更省空间。
金额浮点类型,此处不建议。日期可以转时间:
一、date型转换成int型
UNIX_TIMESTAMP('1997-10-04 22:23:00') =====> 875996580
二、int型转换成date型
FROM_UNIXTIME(875996580) =====> '1997-10-04 22:23:00'
json
【建议】
- JSON数据类型意义及优点
其实,没有JSON数据类型的支持,我们一样可以通过varchar类型或者text等类型来保存这一格式的数据,但是,为什么还要专门增加这一数据格式的支持呢?其中肯定有较varchar或者text、blob来存储此类型更优越的地方。
保证了JSON数据类型的强校验,JSON数据列会自动校验存入此列的内容是否符合JSON格式,非正常格式则报错,而varchar类型、text类型和blob类型本身是不存在这种机制的。
MySQL同时提供了一组操作JSON类型数据的内置函数。
更优化的存储格式,存储在JSON列中的JSON数据会被转成内部特定的存储格式,允许快速读取。
当服务器再次读取JSON文档时,不需要重新解析文本获取该值。
通过键或数组索引直接查找子对象或嵌套值,而不需要读取文档中的所有值。
通过虚拟列的功能可以对JSON中的部分数据进行索引。
存储的容量大,近似于LongBlob与LongText(4G)。
- JSON数据类型缺点
有了虚拟列,似乎一张表只需包含一个int类型的id,一个json类型的content就行了,需要搜索和排序的通过建立虚拟列的方式,但是如果列比较多会增加mysql本身的维护成本。
json的格式要固定,不能随意更改,因为代码是和格式强耦合的,如果变了那要大改,所以这就是mysql和mongodb这类nosql的一个区别,mysql并不是无模式的,对于一张表的那个json字段,模式其实也是固化在json里面而已。
对单体类修改,mybatis自动生成的类不能用,需要自己写sql,属性名称千万不能弄错,没有语法提示,错了不容易发现。
开发成本(写代码)的成本增加。
维护的成本增加,如果后面需要对json里面的另外一个字段进行模糊查找和排序,那么得增加虚拟列,重建索引,代码也要改,而如果是结构化的数据,只要一个DDL即可。
json看似更灵活,其实非常不灵活,远不如结构的数据灵活,通过update的语句,我们其实可以看出来部分修改的操作,比如JSON_SET,并不是实际只修改部分的数据,而是把全量的数据加载到内存,然后修改部分数据,在把修改后的全量的数据设值到mysql中,只不过mysql提供了函数让我们方便的操作json而已。
ETL过程中会涉及到类型转换,增加转换复杂度。
- 数据库JSON字段设计思路
JSON内容不应该是多表需要的。比如一些信息其实是被多表共享的,这就不可以了,因为存在一个更新批量的问题。JSON内容一旦修改/创建其实是要影响多个表,那么慎用JSON。
JSON内容应该是依附性比较强,比如阶段信息永远都是依附于任务而存在,如果有逻辑要单独针对"阶段"内容进行处理,或者在表的概念上有需要以"阶段表"做主表的情况下,JSON化慎用,最好是单独处理为一张表。
JSON中的字段作为检索条件的慎用,尽管MySql支持对于JSON的使用,但是如果数据库服务器还要对JSON进行解析再处理无疑在效率上是有问题的。
JSON不能有默认值并且禁止设置为NOT NULL。
text、blob
【强制】
建议把 BLOB 或是TEXT列分离到单独的扩展表中
MySQL 内存临时表不支持 TEXT、BLOB 这样的大数据类型,如果查询中包含这样的数据,在排序等操作时,就不能使用内存临时表,必须使用磁盘临时表进行。
而且对于这种数据,MySQL 还是要进行二次查询,会使 SQL 性能变得很差,但是不是说一定不能使用这样的数据类型。
如果一定要使用,建议把 BLOB 或是 TEXT列分离到单独的扩展表中,查询时一定不要使用 select * 而只需要取出必要的列,不需要 TEXT列的数据时不要对该列进行查询。
TEXT 或 BLOB 类型只能使用前缀索引,因为 MySQL 对索引字段长度是有限制的,所以 TEXT或 BLOB 类型只能使用前缀索引,并且 TEXT或 BLOB列上是 不能有默认值并且不能为NULL。 TINYTEXT和TEXT请使用VARCHAR类型代替, 因为varchar是变长存储,比char更省空间。MySQL server层规定一行所有文本最多存65535字节,因此在utf8mb4字符集下最多存16383个字符,超过会自动转换为mediumtext字段。而text在utf8mb4字符集下最多存16382个字符,mediumtext最多存(2^24-1)/4个字符,longtext最多存(2^32-1)/4个字符。
ETL过程中会涉及到类型转换或者不支持类型,增加转换复杂度或者无法转换。
TEXT、BLOB不能有默认值并且禁止设置为NOT NULL。
varchar
【建议】
经常变化的字段用varchar;
知道固定长度的用char;
超过255字节的只能用varchar;
能够用数字类型的字段尽量选择数字类型而不用字符串类型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了;
必须有默认值且不能为NULL。
视图的应用
【强制】
MySQL在处理视图时有两种算法,分别称为MERGE和TEMPTABLE。
在执行"CREATE VIEW"语句时可以指定使用哪种算法。不显式指定的话,Mysql默认使用Merge算法。
MERGE,将视图sql合并到主查询sql中,重新构成新sql进行查询。
TEMPTABLE,见文知意,就是将视图当作临时表来处理。
所谓MERGE是指在处理涉及到视图的操作时,将对视图的操作根据视图的定义进行展开,有点类似于C语言中的宏展开。
一般来说在能够使用MERGE算法的时候MySQL处理视图上没什么性能问题,因为可以使用索引、mysql查询优化算法,但并非在任何时候都能使用MERGE算法。事实上,只要视图的定义稍稍有点复杂,MySQL就没办法使用MERGE算法了。准确的说,只要视图定义中使用了以下SQL构造块就无法使用MERGE算法:
聚集函数
DISTINCT
GROUP BY
HAVING
集合操作(UNION, UNION ALL)
子查询
对于复杂视图定义,MySQL使用了一种以不变应万变的方法,即先执行视图定义,将其结果使用临时表保存起来,这样后续对视图的操作就转化为对临时表的操作。不能不说从单从软件设计的角度看,这样的方法非常的优雅,然而从性能角度,这一方法也是非常的差。
使用注意事项:
1)尽量让视图采用merge算法,视图定义中避免DISTINCT、GROUP BY等集合相关运算;
2)如果视图很复杂采用TEMPTABLE的话,想办法减少TEMPTABLE记录数。
慢查询
【高危】
慢查询被称为压垮数据库的最后一棵稻草,可见优化慢查询有多么地重要,然而优化慢查询的难点不在于如何优化,而是在于优化的贯彻力。比如监测出来的慢查询,如若重构SQL需要其他部门配合,那么需要很强的贯彻力,在规定的时间内由DBA发起重构SQL技术指导意见,其他部门结合业务情况重新生成SQL提交至DBA审核,如若通过予以上线,如若不通过打 回再次修改,直至可以通过审核上线,否则优化慢查询也只是停留在优化慢查询会议上。
缓存参数优化
从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级。所以,要优化数据库,首先第一步需要优化的就是IO,尽可能将磁盘IO转化为内存IO。从MySQL 数据库IO相关参数(缓存参数)的角度来看看可以通过以下参数进行IO优化(建议级):
· query_cache_type : 如果全部使用innodb存储引擎,建议为0,如果使用MyISAM 存储引擎,建议为2,同时在SQL语句中显式控制是否使用query cache;
· query_cache_size: 根据命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))进行调整,一般不建议太大,256MB可能已经差不多了,大型的配置型静态数据可适当调大;
· binlog_cache_size: 一般环境2MB~4MB是一个合适的选择,事务较大且写入频繁的数据库环境可以适当调大,但不建议超过32MB;
· key_buffer_size: 如果不使用MyISAM存储引擎,16MB足以,用来缓存一些系统表信息等。如果使用 MyISAM存储引擎,在内存允许的情况下,尽可能将所有索引放入内存,简单来说就是“越大越好”;
· bulk_insert_buffer_size: 如果经常性的需要使用批量插入的特殊语句(上面有说明)来插入数据,可以适当调大该参数至16MB~32MB,不建议继续增大,某人8MB;
· innodb_buffer_pool_size: 如果不使用InnoDB存储引擎,可以不用调整这个参数,如果需要使用,在内存允许的情况下,尽可能将所有的InnoDB数据文件存放如内存中,同样将但来说也是“越大越好”;
· innodb_additional_mem_pool_size: 一般的数据库建议调整到8MB~16MB,如果表特别多,可以调整到32MB,可以根据error log中的信息判断是否需要增大;
· innodb_log_buffer_size: 默认是1MB,系的如频繁的系统可适当增大至4MB~8MB。当然如上面介绍所说,这个参数实际上还和另外的flush参数相关。一般来说不建议超过32MB;
· innodb_max_dirty_pages_pct: 根据以往的经验,重启恢复的数据如果要超过1G的话,启动速度会比较慢,几乎难以接受,所以建议不大于1GB/innodb_buffer_pool_size(GB)*100这个值。当然,如果你能够忍受启动时间比较长,而且希望尽量减少内存至磁盘的flush,可以将这个值调整到90,但不建议超过90。
注:以上取值范围仅仅只是根据以往遇到的数据库场景所得到的一些优化经验值,并不一定适用于所有场景,所以在实际优化过程中还需要大家自己不断的调整分析
相关推荐
- Python自动化脚本应用与示例(python办公自动化脚本)
-
Python是编写自动化脚本的绝佳选择,因其语法简洁、库丰富且跨平台兼容性强。以下是Python自动化脚本的常见应用场景及示例,帮助你快速上手:一、常见自动化场景文件与目录操作...
- Python文件操作常用库高级应用教程
-
本文是在前面《Python文件操作常用库使用教程》的基础上,进一步学习Python文件操作库的高级应用。一、高级文件系统监控1.1watchdog库-实时文件系统监控安装与基本使用:...
- Python办公自动化系列篇之六:文件系统与操作系统任务
-
作为高效办公自动化领域的主流编程语言,Python凭借其优雅的语法结构、完善的技术生态及成熟的第三方工具库集合,已成为企业数字化转型过程中提升运营效率的理想选择。该语言在结构化数据处理、自动化文档生成...
- 14《Python 办公自动化教程》os 模块操作文件与文件夹
-
在日常工作中,我们经常会和文件、文件夹打交道,比如将服务器上指定目录下文件进行归档,或将爬虫爬取的数据根据时间创建对应的文件夹/文件,如果这些还依靠手动来进行操作,无疑是费时费力的,这时候Pyt...
- python中os模块详解(python os.path模块)
-
os模块是Python标准库中的一个模块,它提供了与操作系统交互的方法。使用os模块可以方便地执行许多常见的系统任务,如文件和目录操作、进程管理、环境变量管理等。下面是os模块中一些常用的函数和方法:...
- 21-Python-文件操作(python文件的操作步骤)
-
在Python中,文件操作是非常重要的一部分,它允许我们读取、写入和修改文件。下面将详细讲解Python文件操作的各个方面,并给出相应的示例。1-打开文件...
- 轻松玩转Python文件操作:移动、删除
-
哈喽,大家好,我是木头左!Python文件操作基础在处理计算机文件时,经常需要执行如移动和删除等基本操作。Python提供了一些内置的库来帮助完成这些任务,其中最常用的就是os模块和shutil模块。...
- Python 初学者练习:删除文件和文件夹
-
在本教程中,你将学习如何在Python中删除文件和文件夹。使用os.remove()函数删除文件...
- 引人遐想,用 Python 获取你想要的“某个人”摄像头照片
-
仅用来学习,希望给你们有提供到学习上的作用。1.安装库需要安装python3.5以上版本,在官网下载即可。然后安装库opencv-python,安装方式为打开终端输入命令行。...
- Python如何使用临时文件和目录(python目录下文件)
-
在某些项目中,有时候会有大量的临时数据,比如各种日志,这时候我们要做数据分析,并把最后的结果储存起来,这些大量的临时数据如果常驻内存,将消耗大量内存资源,我们可以使用临时文件,存储这些临时数据。使用标...
- Linux 下海量文件删除方法效率对比,最慢的竟然是 rm
-
Linux下海量文件删除方法效率对比,本次参赛选手一共6位,分别是:rm、find、findwithdelete、rsync、Python、Perl.首先建立50万个文件$testfor...
- Python 开发工程师必会的 5 个系统命令操作库
-
当我们需要编写自动化脚本、部署工具、监控程序时,熟练操作系统命令几乎是必备技能。今天就来聊聊我在实际项目中高频使用的5个系统命令操作库,这些可都是能让你效率翻倍的"瑞士军刀"。一...
- Python常用文件操作库使用详解(python文件操作选项)
-
Python生态系统提供了丰富的文件操作库,可以处理各种复杂的文件操作需求。本教程将介绍Python中最常用的文件操作库及其实际应用。一、标准库核心模块1.1os模块-操作系统接口主要功能...
- 11. 文件与IO操作(文件io和网络io)
-
本章深入探讨Go语言文件处理与IO操作的核心技术,结合高性能实践与安全规范,提供企业级解决方案。11.1文件读写11.1.1基础操作...
- Python os模块的20个应用实例(python中 import os模块用法)
-
在Python中,...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)