搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
从前慢现在也慢
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
jQuery(选择器)_选择id为one的下一个div元素
2
[图解]SysML和EA建模住宅安全系统-01_sysml和ea区别
3
PHP 关于微信小程序安全检测一直返回OK的解决_微信小程序安全测试
4
编译原理实验(1)——词法分析器_山东大学软件学院编译原理实验
5
iptables屏蔽ip某个端口访问_iptables禁止访问某个端口
6
机器学习笔记 KAN网络架构简述(Kolmogorov-Arnold Networks)
7
前端2年经验,历时一个月的面经和总结_qt面经
8
rabbitmq php延迟队列,PHP实战RabbitMQ之延时队列篇
9
java数组、链表实现栈_数组实现栈 链表实现栈
10
浅谈Hive(分布式SQL计算工具)
当前位置:
article
> 正文
mysql数据库设计规范浅谈(一)_mysql数据库设计看法
作者:从前慢现在也慢 | 2024-05-20 23:32:32
赞
踩
mysql数据库设计看法
《mysql设计规范》
数据结构设计
:逻辑设计 –> 物理设计
实际工作
中:逻辑设计 + 物理设计
物理设计
:表名,字段名,字段类型
磁盘IO和操作系统类型,对mysql的性能是非常大的
一. 数据库命名规范
所有的数据库对象名称必须
使用小写字母并用下划线
表示,因为默认情况下,mysql对大小写敏感,mysql数据库本质上是linux系统下的一个文件,而linux系统是大小写敏感的
所有数据库对象名称
禁止使用mysql保留关键字
数据库对象的命名要能做到见名知意,并且最好不要超过32个字符。太长不方便使用,并且会在传输时增加网络开销
临时表
必须以tmp_为前缀并以日期为后缀
备份表
必须以bak_为前缀并以日期为后缀
所有存储相同数据的列名和列类型必须一致,比如user表中的id和order表中的user_id
二. 数据库基本设计规范
所有表必须使用Innodb存储引擎
极少数特殊业务需求除外
Innodb引擎是5.6之后的默认存储引擎;mysql5.5之前使用Myisam(默认存储引擎)
Innodb优点:支持事务,行级锁,更好的恢复性,高并发下性能更好
数据库和表的字符集统一使用UTF-8
如果要存储一些如表情符号的,还需使用UTF-8的拓展字符集
数据库,表,字段字符集一定要统一,统一字符集可以避免由于字符集转换产生的乱码
在mysql中UTF-8字符集,汉字占3字节,ASCII码占1字节
所有表和字段都需要添加注释
从一开始就进行数据字典的维护
即数据库说明文档
尽量控制单表数据量大小
,
建议控制在500万以内,虽然500万并不是mysql的数据库限制,但是会给修改表结构,备份,恢复带来很大困难。
单表可存储数据量大小取决于存储设置和文件系统
想减少单表数据量:历史数据归档(常见于日志表),分库分表(常见于业务表),分区表
建议不要使用mysql分区表,因为分区表在物理上表现为多个文件,在逻辑上表现为一个表。如果一定要分区,请谨慎选择分区键,跨分区查询效率比查询大数据量的单表查询效率更低
建议采物理分表的方式管理大数据,但是对应用程序的开发要求和复杂度更高
尽量做到
冷热数据分离,减少表的宽度(字段数)
减少磁盘IO,保证热数据的内存缓存命中率,更有效的利用缓存,避免读入无用的冷数据
这样的话,就要对表的列进行拆分,将经常使用的列放到一个表中,可以避免过多的关联操作,也可以提高查询性能
禁止在表中建立预留字段
预留字段很难做到见名知义,预留字段无法确定存储的数据类型,后期如果修改字段类型,会对全表锁定,严重影响数据库的并发性
对目前mysql来说,修改一个字段的成本要远远大于增加一个字段的成本
禁止在数据库中存储图片,文件等二级制数据
这类数据如果要存,就得使用blog或者text这样的大字段加以存储,会影响数据库的性能
文件这种通常所占数据容量很大,会在短时间内造成数据库文件的快速增长,而数据库在读取数据时,会进行大量的随机IO操作,如果数据文件过大,IO操作会非常耗时,从而影响数据库性能
正确做法是将这类数据存储在文件服务器中,而数据库只村存储地址信息
禁止在线上做数据库压力测试
会对正常业务造成影响,也会产生很多垃圾数据
建议建立专门的压力测试数据库,进行测试,然后对比测试服务器和线上服务器的硬件环境,评估线上数据库的性能
禁止从开发环境,测试环境直连生产环境数据库
三. 索引设计规范(Innodb中主键实质上是一个索引)
限制每张表上索引数量
,建议单表不超过5个索引。索引并不是越多越好,可以提高查询效率,但是会降低插入和更新的效率。甚至在一些情况下,还会降低查询效率,因为mysql优化器在选择如何优化查询时,会根据统计信息,对每一个可用索引来进行评估,以生成一个最好的执行计划,如果同时有很多索引都可以用于查询,就会增加mysql查询优化器生成查询计划的时间。
每个Innodb表都必须有一个主键
。Innodb是一种索引索引组织表,是指数据存储的逻辑顺序和索引的顺序是相同,Innodb是按照主键索引的顺序来组织表的,因此,每个Innodb表都必须要有一个主键,如果我们没有指定主键,那么Innodb会优先选择表中第一个非空唯一索引来作为主键,如果没有这个索引,那么Innodb会自动生成一个占6字节的主键,而这个主键的性能并不是最好。
不使用更新频繁的列作为主键,不使用多列联合主键
。因为Innodb是一种索引索引组织表,如果主键上的值频繁更新,就意味着数据存储的逻辑顺序频繁变动,必然会带来大量的IO操作,降低数据库性能。
不要使用uuid,md5,hash,字符串列作为主键
。因为这种主键不能保证主键的值是顺序增长的,如果后来的主键值在已有主键值的中间段,那么这个主键插入的时候,会将所有主键值大于它的列都向后移。
最好选择能保证值的顺序为顺序增长的列为主键
。并且数据不能重复,建议用mysql自增id建立主键
面试问题1:
要在哪些列上建立索引?
在select,delete,update的where从句中的列
包含在order by,group by,distinct字段中的列
多表join的关联列:mysql对关联操作的处理方式只有一种,那就是嵌套循环的关联方式,所以这种操作的性能对关联列上的索引的依赖性很大
面试问题2:
复合索引,如何选择索引列的顺序?
从左到右的顺序来使用的
区分度(列中group by的数目和此列总行数的比值趋近于1)最高的列放在联合索引的最左侧
在区分度差不多的情况下,尽量吧字段长度小的放在联合索引的最左侧,因为同样的行数,字段小的文件也小,读取时IO性能更优
使用最频繁的列放在联合索引的左侧,这样的话,可以较少地建立索引就能满足需求
避免建立冗余索引和重复索引
对于频繁的查询优先使用覆盖索引
就是包含了所有查询字段的索引,这样可以避免Innodb表进行索引的二次查找,并可以把随机IO变为顺序IO提高查询效率
尽量避免使用外键
mysql和别的数据库不同,会自动在外键上建立索引,会降低数据库的写性能
建议不使用外键约束,但是一定要在表与表之间的关联键上建立索引,虽然外键是为了保证数据的完整性,但是最好在代码中去保证。
四. 字段设计规范
优先选择符合存储需要的最小的数据类型
尽量将字符串转化为数字类型存储:如将ip存储为数字:inet_aton(‘255.255.255.255’) = 4294967295 ,反之, inet_ntoa(4294967295) = ‘255.255.255.255’
对于非负整型数据,优先使用无符号整型来存储,如:id,age,无符号相对于有符号,可以多出一倍的存储空间
mysql中,varchar(n)中n表示字符数而不是字节数
避免使用text,blog来存储
字段,这种类型只能使用前缀索引,如果非要使用,建议将这种数据分离到单独的拓展表中
避免使用enum类型
。枚举本身是一个字符串类型,但是内部确是用正数类型来存储的,所以最多可存储65535种不同的值,修改的话必须使用alter语句,直接修改元数据,有操作风险;order by效率低,必须转换并无法使用索引,禁止使用数值作为enum值,因为enum本身是索引顺序存储的,会造成逻辑混淆
尽可能把所有列定义为not null
。
索引null列需要额外的空间来保存,占更多空间
进行比较和计算时,对null值作特别的处理,可能造成索引失效
禁止使用字符串来存储日期型数据
。
无法使用日期函数计算比较
字符串存储要占更多的内存空间,datetime(8字节)和timestamp(本身是以int存储,占4字节,范围:1970-01-01 00:00:01到2038-01-19 03:14:07)
财务相关数据,使用decimal类型
(精准浮点类型,在计算时不丢失精度)。
五. SQL开发规范
建议使用预编译语句(prepareStatment)进行数据库操作
可以同步执行预编译计划,减少预编译时间
可以有效避免动态sql带来的SQL注入的问题
只传参数,一次解析,多次使用,比传递sql语句更高效
避免数据类型的隐式转换
一般出现在where从句中,会导致索引失效,如:select id,name from user where id = ‘12’;
充分利用已存在的索引
避免使用双%的查询条件,不走索引
一个SQL只能利用到复合索引中的一列进行范围查询
使用left join或not exists来优化not in操作
程序连接不同的数据库使用不同的账号,禁止跨库查询
为数据库迁移和分库分表留出余地
降低业务耦合度
避免权限过大而产生的安全风险
禁止使用select * 来查询,必须用字段名
可能会消耗更多的cpu和IO以及网络资源
无法使用覆盖索引
可以减少表结构变更对已有程序的影响
禁止使用不含字段列表的insert语句
。
可以减少表结构变更对已有程序的影响
禁止使用子查询
虽然可使sql可读性好,但是缺点远远大于优点
子查询返回的结果集无法使用索引,结果集会被存储到一个临时表中,结果集越大性能越低
把子查询优化为join操作,但是并不是所有的都可以优化为join,一般情况下,只有当子查询是在in字句中,并且子查询是一个简单的sql(不包含union,group by,order by,limit)才能转换为关联查询
避免join过多的表
每join一个表会占一部分内存(join_buffer_size)
会产生临时表操作,影响查询效率
mysql最多允许关联61个表,建议不超过5个
减少同数据库的交互次数
数据库更适合处理批量操作
合并多个相同的操作到一起,提高处理效率
使用in代替or
in的值不要超过500个
in 操作可以有效利用索引
禁止使用order by rand()进行随机排序
会把表中所有符合条件的数据装载到内存中进行排序
会消耗大量的cpu和io及内存资源
推荐在程序中获取随机值
禁止在where从句中对列进行函数转换和计算
导致无法使用相关列上的索引
where date(create_time)=’20170901’
写成
where create_time >= ‘20170901’ and create_time < ‘20170902’
在明显不会有重复值时使用union all而不是union
union 会把所有数据放在临时表中后再进行去重操作,会多消耗内存,IO,网络资源
union all 不会再对结果集进行去重操作
拆分复杂的大sql为多个小sql
目前mysql中一个sql只能使用一个cpu计算,不支持多cpu并行计算
sql拆分后可以通过并行执行来提高处理效率
六. 数据库操作行为规范
主要面向手动操作数据库的行为
超过100万的批量写操作,要分批多次进行操作
主从复制中:大批量操作可能会造成严重的主从延迟,因为当主库执行完成后,才会在从库执行
binlog日志为row格式时会产生大量的日志
避免产生大量事务,产生阻塞,占满可用连接
对大表数据结构的修改一定要谨慎
可能会造成严重的锁表操作,尤其是生产环境,是不能忍受的
对于大表使用pt-online-schema-change修改表结构:
首先会建立一个与原表结构相同的新表
然后在新表上进行表结构的修改
然后把原表中的数据复制到新表中,并且增加一些触发器,以便把原表中即时新增的数据也复制到新表中
在行的所有数据复制完成之后,会在原表上增加一个很准的时间锁,同时把新表命名为原表,把原表删掉
[实际上是把一个原子的DDL操作分解成多批次进行]
[避免大表修改产生的主从延迟问题]
[避免在对表字段进行修改时进行锁表]
禁止为程序使用的账号赋予super权限
当数据库连接数达到最大限制时,允许1个有super权限的用户连接
super权限只能留给DBA处理问题的账号使用
对于程序连接数据库账号,遵循权限最小原则
程序使用的数据库账号只能在一个DB下使用,不准跨库
程序使用的账号原则上不准有drop权限
其余的后续补充
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/599857
推荐阅读
article
【
mysq
l】
mysq
l单表
查询
、
多表
查询
、
分组
查询
、子
查询
等案例详细解析_
mysq
分组
查询
和
多表
查...
子
查询
可以单独作为临时数据,作为一张表或者一个字段,通过()进行包裹,表达一个整体; 一般用在from,where,s...
赞
踩
article
Anolis
7.9
+ Mysql 8.0.32 安装_
operating
system
: ano...
Anolis
7.9
+ Mysql 8.0.32 安装_
operating
system
:
anolis
os
7.9
...
赞
踩
article
Linux
(centos)安装
MySQL
8
数据库
(图文详细教程)_软件包
mysql
-comm...
前几天写了个window系统下安装Mysql的博客,收到很多小伙伴私信需要
Linux
下安装Mysql的教程,今天这边和大...
赞
踩
article
My
SQL
慢
SQL
可能原因汇总_
慢
sql
原因...
My
SQL
慢
SQL
可能原因汇总_
慢
sql
原因
慢
sql
原因 在对服务器进行性能分析时,我们...
赞
踩
article
Linux
下 Mysql 区分
大小写
_
linux
mysql
区分
大小写
...
Linux
下 Mysql 区分
大小写
问题描述将 SpringBoot 项目部署到
linux
服务器之后,运行数据库报...
赞
踩
article
ModuleNotFoundError
: No
module
named
‘
mysql
‘
解决方案
_m...
第一:首先要命令 “pip list"查看自己的
mysql
-connector模块是否已经安装了。第二:到pycharm...
赞
踩
article
mysql
数据库
基础
教程
(一)_
数据库
教程
...
mysql
数据库
基础
教程
_
数据库
教程
数据库
教程
目录 1.操作
数据库
和表(DDL) 1.
数据库
...
赞
踩
article
mysql
提交
事务_
MySQL
事务
提交
过程...
一、
MySQL
事务
提交
过程(一)
MySQL
作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中。今天我们来讨论下事务...
赞
踩
article
RedHat7
安装
MySQL
5.7
_redhat服务器离线
安装
mysql
5.7
tar
...
一、
MySQL
下载通过官网下载:https://dev.mysql.com/downloads/mysql/,或者我这里...
赞
踩
article
小知识点:ARM 架构 Linux 大数据集群基础环境搭建(
Hadoop
、
MySQL
、
Hive
、Sp...
ARM 架构 Linux 大数据集群基础环境搭建(
Hadoop
、
MySQL
、
Hive
、
Spark
、
Flink
、ZK、Ka...
赞
踩
article
Linux
系统
MySQL
-
8.3
.0
安装
流程_
linux
安装
mysql
8.3
...
MySQL
官网: https://www.mysql.com/downloads/将
MySQL
压缩文件移动到自己心仪的位...
赞
踩
article
linux
配置
mysql
_
linux
mysql
8.3...
export PATH=$PATH:/path/to/
mysql
/bin (path为你自己的实际路径)保存生效:so...
赞
踩
article
MySQL
高级知识之
使用
mysqldump
备份
和恢复...
mysqldump
是
MySQL
自带的
备份
工具,它可以实现对 MyISAM 表的温
备份
和对 innodb 表的热
备份
。...
赞
踩
article
mysql
mysql
dump 命令
备份
数据
_
mysql
dump -a...
mysql
mysql
dump 命令
备份
数据
数据
备份
常用命令
mysql
dump -A -uroot -p > xxx.s...
赞
踩
article
MYSQL
操作+C语言
API
_
c
mysql
api...
2.建数据库default
c
harset=utf8使数据库可以使用中文。4.建表5.查看6.删除7.插入8.更新二、C...
赞
踩
article
C/
C++
使用
MySQL
API
进行
数据库
操作_
mysql
c++
api...
随着信息时代的到来,
数据库
的应用日益广泛,
MySQL
作为开源的关系型
数据库
管理系统,被广大开发者所喜爱。在 C/
C++
...
赞
踩
article
MySQL
C语言
API
总结_
mysql
c api...
在实际应用中,我们不可能在命令行登录进数据库进行数据的查询、插入等操作,用户一般是使用一个界面良好的应用程序软件来对...
赞
踩
article
[Mysql]
STR
_TO_
DATE
函数
_
strtodate
函数
...
本文主要讲解
STR
_TO_
DATE
函数
_
strtodate
函数
strtodate
函数
STR
_T...
赞
踩
article
MySQL
,
STR
_
TO
_
DATE
() 函数详解_
mysql
strtodate
...
在
MySQL
中,
STR
_
TO
_
DATE
() 函数用于将一个字符串转换为日期或时间格式。它可以帮助我们将字符串解析为日...
赞
踩
article
my
sql
todate
的
sql
_
MySQL
数据库
之
MySQL
STR
_TO_
DATE
() 函数...
本文主要向大家介绍了
MySQL
数据库
之
MySQL
STR
_TO_
DATE
() 函数 ,通过具体的内容向大家展现,希望对大...
赞
踩
相关标签
mysql
数据库
mysql单表查询
mysql多表查询
分组查询
SQL聚合函数
linux
centos
sql
docker
python
pycharm
自动化
database
mysql 提交事务
Linux
Redhat
MySQL
大数据