目录

mysql数据表设计经验汇总篇

mysql数据表设计经验汇总篇
一,命名,见名知意,命名规范,命名可读性高,尽量使用英文,采用驼峰命名。
1,表名:customer_id,order_date,product_name
2,字段名:customer_id,order_date,product_name
3, 索引名:idx_customer_id,idx_order_date

Tips

1) 表名,字段名必须使用小写字母,禁止使用数字开头,禁止使用拼音,并且一般不使用英文缩写。
2)主键索引名为 pk字段名,唯一索引名为 uk字段名;普通索引名则为idx_字段名
二, 选择合适的字段类型
设计表前,需要选择合适的字段类型,比如说:
1,根据数据类型选择字段类型:不同的数据类型应该使用不同的数据类型
1),整数型数据可以使用INT或者BIGINT类型
2),浮点型数据可以使用FLOAT或者DOUBLE类型
3),字符型数据可以使用VARCHAR或CHAR类型
2, 考虑数据长度。
1)如果某个字段数据长度不会超过10个字母,则可以使用CHAR(10)类型代替VARCHAR(50)类型,以节省空间。
2)如果存储的值太大,建议字段类型修改为text,同时抽出单独一张表,用主键与之对应。
3,注意精度和小数位数:
对于需要精确数值计算的字段(如货币和百分比),应该选择带有精度和小数位数的字段类型(如DECIMAL).
4,考虑数据完整性:字段类型也应该考虑到数据完整性
日期型数据应该使用DATE或DATETIME类型,以确保输入的日期格式正确。
三,主键设计要合理,MySQL的实现以及二叉树
主键的设计在数据库中非常重要,它用于唯一标识表中的每一行数据,并且在数据操作和查询中起到关键作用。通常主键的设计,不要与业务相关联,因为业务是会发生变化的,应当使用自增的id,并且保持主键的连续性。比如说可以使用优化的雪花ID(分布式系统)[uuid不推荐使用]。
四,选择合适的字段长度
首先问大家一个问题,数据库字段长度表示字符长度还是字节长度?
在mysql中,VARCHAR和CHAR类型表示字符长度,而其他类型表示的长度都是表示字节长度。
CHAR(10)表示字符长度是10
bigint(4)表示显示长度是4个字节,但因为bigint实际长度是8个字节,所以bigint(4)的实际长度就是8个字节。
所以在设计表时需要考虑一个字段的长度,比如一个用户名字段(它的长度5-20个字符),你觉得应该设置多长呢?可以考虑设置为VARCHAR(32),需要注意用户名字段长度一般设置为2的n次方,注意java中Hash Map的长度(2的n次方)
五,优先考虑逻辑删除,而不是物理删除
什么是物理删除?什么是逻辑删除?
1)物理删除:把数据以硬盘中删除,可释放存储空间。
2)逻辑删除:给数据添加一个字段,比如is_deleted,以标识该数据已经逻辑删除。
为什么推荐使用逻辑删除,不推荐物理删除呢?
1)数据恢复困难
2)物理删除会导致索引树重构。
六,每个表需要添加通用字段
1)id: 主键,一个表必须得有主键,必须
2)create_time: 创建时间
3)creater: 创建人
4)update_time: 修改时间,必须,更新记录时,需要更新它
5)update_by: 修改人,非必须
6)remark: 数据记录备注,非必须
七,一张表的字段不宜过多
建表的时候一张表的字段不要太多,尽量不超过20个,超出的话优先考虑撤分,也就是通常的查询表,详情表
1)查询效率:当表中保持的数据数量很大时,查询操作需要检查的数据也会随之增加;如果表的字段数过多,查询操作就需要读取更多的数据,这会导致查询效率变慢。
2)存储空间:表的字段数越多,每一行数据占用的存储空间也就越大。对于大型数据库来说,这个可能会导致磁盘空间的浪费。
3)数据库设计复杂性:当表的字段数过多时,数据库的设计和维护支持变得更加复杂,这可能涉及到索引和关联表的设计,以确保数据的完整性和一致性,
八,定义字段尽可能NOT NULL
如果没有特殊的理由,一般都建议将字段定义为NOT NULL:
1) 首先,NOT NULL 可以防止出现空指针问题
2)其次,NULL值存储也需要额外的空间的,它也会导致比较运算更为复杂,使用优化器,难以优化SQL,
3) NULL值可能会导致索引失效。
如果将字段默认设置成一个空字符串或常量值,并没有什么不同,且都不会影响到应用逻辑,那就可以将这个字段设置为NOT NULL
九,合理添加索引
当设计表时,需要考虑哪些字段需要加索引,可以遵循以下几个原则:
1,根据在查询中使用了某个字段作为查询条件,那么这个字段应该建立索引。例如,在用户表中,如果需要根据用户的姓名进行查询,那么就应该为姓名字段建立索引。
2,区分度高的字段优先:如果一个字段的取值范围非常小,例如:性别只有男和女两种可能,那么这个字段就不适合建立索引。相反,如果某一个字段的取值范围很大且区分度高,例如:用户ID,那么就这个字段就非常适合建立索引。
3,不要建立过多索引:每个表所建立的索引数量应该控制在一个合理的范围内,一般不要超过5个,因为过多的索引会导致写入速度变慢,并占用更多的存储空间。
4,联合索引优化:在某些情况下,可以通过联合索引的方式来优化查询速度,减少所需的索引数量。例如:在用户表中,如果需要根据用户姓名和年龄进行查询,那么可以将这两个字段组合成联合索引。
假设你有一个订单表,包含订单ID,用户ID,订单金额,订单状态等字段,现在需要根据用户ID和订单状态进行查询,可以考虑为用户ID和订单状态这个两个字段建立联合索引,例如:
复制代码
CREATE TABLE order_tab (
    id int(11) NOT NULL AUTO_INCREMENT,
    user_id int(11) NOT NULL,
    amount decimal(10,2) NOT NULL,
    status varchar(20) NOT NULL,
    create_time datetime NOT NULL,
    PRIMARY KEY (id),
    KEY idx_user_status(user_id,status)USING KTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
十,不需要严格遵守3NF,通过业务字段冗余来减小表关联,简单来说就是反范式设计,常见形式是在第三范式(3NF)的基础上,进一步进行冗余,从而减少表关联。
回顾一下什么是数据库三范式(3NF)?
第一范式:对属性的原子性,要求属性具有原子性,不可再分解;
第二范式:对记录的唯一性,要求记录有唯一标识,即实体的唯一性,即不存在部分依赖;
第三范式:对字段的冗余性,要求任何字段,不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖;
假设需要设计一个产品订单表,包含以下字段:订单ID,用户ID,订单日期,产品名称,产品价格,产品数量以及订单总价,正常情况下,可能会分别设计订单表和产品表,并使用外键进行关联,例如:
订单表
复制代码
CREATE TABLE order (
    'id' int(11) NOT NULL AUTO_INCREMENT,
    'user_id' int(11) NOT NULL,
    'order_date' date NOT NULL,
    'product_id' int(11) NOT NULL,
    'quantity' int(11) NOT NULL,
    PRIMARY KEY ('id'),
    FOREIGN KEY('product')REFENCES 'product'('id')
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
十一,避免使用MYSQL保留字
如果库名,表名,字段名等属性含有保留字,SQL语句必须用反引号来引用属性名称,这将使得SQL语句书写,SHELL脚本中变量的转义等变得非常复杂。
如果你需要使用这些保留字作为表名,列名或者其他标识符,你可以考虑以下方法来避免冲突:
1,在标识符前或后添加下划线:例如,将表名命名为 "my_table",列名命名为 "column_name".
2, 使用不同的单词或短语:例如,将表名命名为 "orders_table",列名命名为 "column_name".
3,使用反引号(): 将标识符括起来:例如,将表名命名为 "table",列名命名为 "column",请注意,使用反引号时要小心,确保使用正确的语法和规范。
常见保留字:
复制代码
ADD ALL ALTER AND AS BETWEEN BY CASE DELETE FROM GROUP HAVING INSERT INFO JOIN LIKE
十二,不搞外键关联一般都在代码维护
在数据库设计中,使用外键关联是一种良好的实践,可以确保数据库的完整性和一致性,外键关联可以帮助维护表之间的关系,防止无效或不一致的数据插入,更新或删除操作。然而,在某些情况下,也存在一些缺点,这可能是导致现在不太推荐使用外键关联的原因之一,以下是一些这种情况:
1,可能会导致性能问题,尤其是在对大型数据里进行操作时,这是因为每次插入,更新或删除操作,都需要进行约束检查,这可能会导致额外的开销和延迟。
2,可能会限制数据库的灵活性和可扩展性,例如:如果需要对数据库进行分区或垂直分割,外键关联可能会导致额外的安全性和限制。
3,可能会导致死锁和死循环,特别是在进行开发操作时,这可能会导致数据库出现不稳定的状态,从而影响系统的性能和可用性
4,可能会导致数据库的维护和管理成本的增加,这是因为外键关联需要额外的管理和维护工作,例如:添加,修改或删除外键约束时需要额外的测试和验证。
因此,在决定是否使用外键关联时,需要考虑实际业务需求和场景,并进行数权衡和决策。在某些情况下,可以采用其他方法来保证数据的完整性和一致性。例如,使用应用程序逻辑和数据库触发器来实现约束检查和数据操作。同时,需要注意数据库设计的基本原则和最佳实践,例如,避免数据冗余,遵循规范化原则和正常化理论等。
十三,字段注释
设计表时,每个字段的含义要注释清楚,包括拨号类型。比如说:
复制代码
'order_status' varchar(2) COLLATE utf8_bin NOT NULL COMMENT '订单状态01;待支付02;已支付03;已发货04;已完成05;'
十四,时间的类型选择
时间类型的选择一般都要好好考虑,因为不同的类型存储的格式不同。
对于MYSQL来说,主要有 date ,datetime ,time,timestamp和year.
1, date: 表示的日期值,格式 yyyy-mm-dd,范围1000-01-01到9999-12-31,3个字节
2,time:表示的时间值,格式 hh:mm:ss,范围-838:59:59到838:59:59,3个字节
3,datetime:表示日期时间值,格式 yyyy-mm-dd hh:mm:ss 范围1000-01-01 00:00:00到9999-12-31 23:59:59,8个字节,跟时区无关
4,timestamp: 表示的时间戳值,格式为yyyymmddhhmmss,范围1970-01-01 00:00:01 到2038-01-19 03:14:07,4个字节 跟时区无关
5,year: 年份值,格式为yyyy,范围1901到2155,1个字节
推荐优先使用datetime类型来保存日期和时间,因为存储范围更大,跟时区无关。
十五,SQL编写的一些优化经验
1,避免使用SELECT * FROM 语句,应该只选择需要的列以减少网络传输和提高查询性能。
2,使用索引来提高查询速度,特别是在对大型表进行查询时。
3,避免使用外键约束,因为他们可能会导致性能问题,特别是在对大型表进行插入,更新和删除操作时。
4,使用LIMIT 1来限制查询结果只有一条记录。
5,避免在where子句中使用OR来连接条件,应使用UNION来连接查询。
6,注意优化LIMIT源分页问题,可以使用OFFSET来替代LIMIT.
7,使用where条件限制要查询的数据,避免返回多余的行。
8,尽量避免在索引列上使用MYSQL的内置函数,这可能导致索引无效。
9,应尽量避免在where子句中对字段进行表达式操作,这可能导致索引无效。
10,应尽量避免where子句中使用 != 或 <> 操作符,这可能导致索引无效。
11,使用联合索引的时候,注意索引列的顺序,一般遵循最左匹配原则。
12,对查询进行优化,应考虑在where及order by涉及的列上建立索引。
13,如果插入数据过多,考虑批量插入。
14,在适当的时候,使用覆盖索引。
15,使用EXPLAIN分析 你SQL所计划
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
Linux运维老纪3 天前
运维之 Centos7 防火墙(CentOS 7 Firewall for Operations and Maintenance)
linux·安全·centos·云计算·运维开发·火绒
豪越大豪9 天前
豪越消防一体化安全管控平台:消防管理智能化
大数据·运维开发
Linux运维老纪10 天前
内网YUM源搭建手册(Internal Network yum Source Construction Manual)
linux·网络·阿里云·云计算·运维开发
Linux运维老纪11 天前
Linux之 权限提升(Linux Privilege Escalation)
linux·服务器·数据库·mysql·云计算·运维开发
demonlg011213 天前
Jenkins 共享库(Shared Libraries)使用说明文档
java·运维·python·jenkins·运维开发·devops
demonlg011213 天前
Jenkins CustomTools 插件使用说明文档
运维·jenkins·运维开发·devops
demonlg011213 天前
Jenkins集成Trivy安全漏洞检查指南
java·运维·python·jenkins·运维开发·devops
SG.xf13 天前
k8s的控制应用Helm
linux·运维开发
luckyext15 天前
SQLServer列转行操作及union all用法
运维·数据库·后端·sql·sqlserver·运维开发·mssql
Linux运维老纪16 天前
K8S集群新增和删除Node节点(K8s Cluster Adds and Removes Node Nodes)
linux·云原生·容器·kubernetes·云计算·运维开发