Mysql建表规范备忘录

2024-05-23 06:58

本文主要是介绍Mysql建表规范备忘录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、基础规范

(1) 必须使用INNODB存储引擎

  • SQL:   ENGINE=InnoDB

(2) 创建数据库,字符集统一为utf8mb4,比较规则为utf8mb4_general_ci

      创建数据表,字符集统一为utf8mb4

      (DBA在创建数据库时已经指定比较规则collate属性,开发在提交DDL时,无需再特殊指定,保持跟数据库比较规则一致即可)

  • Utf8mb4可以支持emoji/特殊符号.
  • 统一的数据库字符集以及比较规则可减少字符隐式转换,表关联时提高查询性能
  • 建表时设置 CHARSET=utf8mb4 即可,无需对字段重复设置

(3) 所有表,字段都必须要有注释

  • 注释可增加表的可读性,方便问题查找跟踪
  • SQL:  COMMENT ‘主键ID’

(4) 不使用blobtext等大容量字段

  • 大对象索引会补全所有长度建立索引,效率低
  • 需要额外存储
  • 大字段需放在专门存储服务器上,在数据表字段中存储路径

(5) 表必须创建无符号(unsigned)自增(auto_increment)整型(int,bigint)主键

不要使用非数字类型做主键(防止发生数据、索引块的分裂)

  • id做主键,可以明显减小二级索引大小
  • id可以在去重、查询数据量、统计查询时发挥作用
  • id可以在数据增量拉取和同步时发挥作用
  • SQL:  `id` int unsigned NOT NULL AUTO_INCREMENT comment '主键ID',
  • primary key(`id`)

(6)必须:所有表添加是否删除(deleted)、创建时间(create_time)和更新时间(update_time)字段

  • 是否删除字段.标识该记录是否删除,消除物理删除.(所有记录不允许物理删除,只能通过该标记位标示是否删除),需要开发在程序中维护该字段
  • 创建时间字段.标示记录的创建时间,设置DEFAULT CURRENT_TIMESTAMP由数据库自动维护
  • 更新时间字段.标示记录的更新时间,设置DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP由数据库自动维护
  • 在create_time和update_time列上创建索引,方便检索数据.
  • SQL:
  • `deleted` tinyint not null DEFAULT 0 COMMENT '是否删除 0 未删除 1 删除 默认是0',

 `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间,默认当前时间',       `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间,默认当前时间'

   并且创建基于create_time和update_time的索引

          key idx_create_time(`create_time`);

          key idx_update_time(`update_time`);

 (7) 列尽量避免使用NULL:应该指定列为NOT NULL,除非你想存储NULL

应该用0、一个特殊的值或者一个空串代替空值。

  • 在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂
  • 同时在保存与处理NULL类形时,也会做更多的工作,所以从效率上来说,不建议用过多的NULL

 (8) 字段类型选择与字段长度设计

  • 根据业务场景合理的设计表字段类型以及字段长度
  • 如时间类型字段使用datetime或timestamp
  • 列长度设计需合理,也要考虑扩展性,不宜定义过长,如mobile varchar(20)
  • 如果列长度过长,且需要创建索引时,尽量使用前缀索引,如index idx_abc(abc(20))
  • 禁止在数据库中存储明文密码,把密码加密后存储
  • 存储ip最好用int存储而非char(15),通过MySQL函数inet_ntoa和inet_aton来进行转化。Ipv6地址目前没有转化函数,需要使用DECIMAL或者两个bigINT来存储。
  • 数据库中不允许存储大文件,或者照片,可以将大对象放到磁盘上,数据库中存储它的路径

说明:  MYSQL数据库varchar和char括号后面的数字表示的是最大存储的字符数,  如 varchar(20)可以存放20个字母或汉字 需根据实际使用长度建立合适的字符长度,可使用char_length()函数查看预估将来存储字段长度

常用字段长度建议

        省份   province varchar(10)

        城市   city varchar(10)

        姓名  name varchar(20)

        电话   mobile varchar(20)

        链接   url varchar(128或者255)

        类型type,标示deleted,flag,状态state,status   设置为tinyint

        备注   comment varchar(100或300或500)  需在程序中控制输入字符长度

        所有的ID字段,如stu_id,stu_user_id,user_id,app_id,tea_id等都设置为int类型

        所有的时间字段,如只有日期,则设置为date类型

                                  如含有日期和时间信息,则设置为datetime或timestamp类型

                                  如只有年,月,或者年月信息,则建议设置为char类型

       原则:数据类型选择优先级 timestamp>datetime,date>int>char>varchar>text,blob

  • 数据库字段长度见附录二

(9)不要使用数据库保留关键字

  • 尽量不要使用数据库保留关键字,数据库保留关键字见附录一

(10)命名规范

  • 库名、表名、字段名必须使用小写字母和下划线’_’,不能超过32个字符,不使用关键字,取名需有意义。
  • 备份表以_bak_日期结尾,如"_bak_20191202"
  • 临时表以_tmp_日期结尾,如"_tmp_20191202"
  • 唯一索引以uni_开头,按照"uni_字段名称_字段名称"进行命名
  • 普通索引以idx_开头,按照"idx_字段名称_字段名称"进行命名

(11)不使用外键做数据完整性约束,从业务代码上控制

(12)浮点数类型字段使用decimal,禁止使用floatdouble类型

(13) 不允许使用ENUMSET类型

  • 插入非法值的时候,默认会插入一个空值
  • ddl成本太高
  • 且在比较时存在隐式转换

 

数据库建表示例:

create table test_01(id int unsigned not null auto_increment comment 'ID主键',name varchar(20) not null default '' comment '姓名',sex char(1) not null default '' comment '性别(男,女)',age smallint not null default 0 comment '年龄',address varchar(100) not null default '' comment '地址',phone varchar(20) not null default '' comment '电话',deleted tinyint not null DEFAULT 0 COMMENT '是否删除 0 未删除 1 删除 默认是0',create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间,默认当前时间',update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间,默认当前时间',primary key(id),unique key uni_phone(phone),index idx_name(name),index idx_address(address(20)),index idx_create_time(create_time),index idx_update_time(update_time)) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci comment '示例表';

注:程序中不允许物理删除字段内容,而是通过deleted字段维护数据逻辑删除(该字段开发必须在程序中维护)

 

二、索引规范

(1)主键准则

  • 使用无符号(unsigned),自增(auto_increment),int或bigint列作为ID主键

(2)建立索引原则

  • 单张表中索引数量不超过7个(建议3-4个),组合索引中的字段数不超过3个
  • 区分度高的建立索引(如手机号,时间),区分度低的不建立索引 (如性别,BU信息)
  • 根据SQL建立合理的复合索引,考虑最左前缀原则,一般是区分度较高的放在前边
  • 索引字段的默认值不能为NULL,要改为其他的default或者空。NULL非常影响索引的查询效率
  • 避免冗余和重复索引
  • 索引要综合评估数据密度和分布以及考虑查询和更新比例

 (3)索引使用原则

  • 不在索引列进行数学运算和函数运算
  • 关联字段且需要走索引的字段必须在字符集保持一致,否则无法应用索引
  • 注意隐式转换规则,优先级时间类型>数字类型>字符类型
  • 使用EXPLAIN判断SQL语句是否合理使用索引,尽量避免extra列出现:Using File Sort,Using Temporary
  • 建立索引必须给DBA提供对应的SQL语句或者业务场景,SQL变更需要确认索引是否需要变更并通知DBA
     

三、SQL规范

(1) 事务设计原则:事务要简单,整个事务的时间长度不要太长,默认使用自动提交 

  • 代码中手动开启事务时,一定要显示提交或者回滚事务
  • 禁止可能造成长事务的情况:
  • 程序中手动开启事务,没有在正常结束或者异常结束时关闭事务
  • 事务中含有慢查询、或者外部调用,外部调用失败时,事务没有关闭
  • 在高并发写情况下需合理设计事务:
  • 选择正确的事务隔离级别(默认是Repeatable Read),建议使用Read Committed
  • 需要在数据库解决并发写冲突的,首选乐观锁解决,其次考虑悲观锁。
  • 程序中有请求其他系统服务的,可以做成异步请求或者放到事务外边
  • 保证事务中所有的dml语句有序执行

(2)优化原则

  • 业务端需要控制减少数据查询范围

解读:减少数据查询范围,能减少数据库压力并提高响应时间.(许多慢SQL都是因为没有控制查询范围引起的)程序应该在源端控制查询范围,不能大范围查询数据.

  • 不要用select *,查询哪几个字段就select 这几个字段

解读:避免后期如果表字段做了增加操作而导致的应用异常;有大字段的表,减少不必要的 IO;减少无用数据检索;需要 GROUP BY 和 ORDER BY 的减少不必要的数据排序

  • SQL语句尽可能简单,尽量减少JOIN操作
  • 禁止在业务数据库环境写复杂的多表关联查询

解读:开发人员在设计可以逆范式,同时考虑冗余字段的实时性以及扩展性问题

       关联查询需要消耗大量的数据库资源,导致数据库性能下降.

  • 索引字段不要出现隐式转换,优先级时间类型>数字类型>字符类型

解读:比如mobile字段是varchar类型,且有索引,如下语句会导致不走索引,select from where mobile=11111111111;

  • 在SQL语句中,禁止使用前缀是%的like模糊匹配查询

解读:可以从业务端优化,比如先在前端实现模糊匹配,然后传入到后台;如果非得实现全文检索功能,可以考虑ES大表分页注意效率。

  • 注意大表分页查询效率,Limit越大,效率越低。

解读:可以改写limit,比如:
select id from t limit 10000, 10; => select id from t where id > 10000 limit10;
SELECT FROM table ORDER BY TIME DESC LIMIT 10000,10; => SELECT FROM table WHERE TIME<last_TIME ORDER BY TIME DESC LIMIT 10. => SELECT FROM table inner JOIN(SELECT id FROM table ORDER BY TIME LIMIT 10000,10) as t USING(id)

  • 判断一个结果集中的记录是否在另一个结果集中存在,用exists优于in、any或者count()
  • 注意AND和OR运算符的优先级,AND运算符的优先级高于OR运算符,如果WHERE条件中同时出现,务必使用小括号明确优先级
  • 索引尽量不使用NOT的否定谓词,使用NOT EXISTS代替NOT IN

解读:首先是效率问题,其次是在使用NOT IN时,子查询只要有一个值是null,那么没有结果命中

  • 不要在where条件中对索引列使用or

解读:同一个字段改写成where in list方式,不同字段采用union、union all方式

  • 大表更新时,不要一次全部更新,分批次更新。

解读:
对数据的更新要打散后批量更新如一次更新2000条记录,不要一次更新太多数据。对于这种操作不要先查询出批次数据,再逐条更新,使用update xxx where 更新字段=未更新值 limit 2000,根据返回的更新行数来判断是否已经更新完毕

  • IN条件里面的数据数量要少

解读:mysql虽然没有in list个数限制和sql长度限制,但是对于数据包的大小限制,通过max-allowed-packet设置,默认时4MB。

  • 使用MySQL的explain进行执行计划分析

解读:通过explain查看sql的执行计划,优化SQL避免对数据表做全表扫描操作

(3)程序设计原则

  • 写SQL语句采用集合的思想,而不是记录的思想
  • 如非特殊需求,必须使用连接池连接数据库,保证会话是长连接。
  • 根据业务系统进行合理的读写分离,支付、实时性要求较高的业务场景不要做读写分离。
  • OLTP业务使⽤绑定变量方式(变量通过占位符方式,而非字符串拼接方式)

解读:一次解析,多次使用;降低SQL注入概率;如果是分析型系统最好采用直接量,采用绑定变量情况在直方图分布不均匀情况下出现执行计划错误情况

  • 禁止使用触发器、函数、存储过程

解读:暴露在应用程序之外,不可控,调试困难

 

四、流程规范

(1) 所有的线上操作,需要提前向DBA提交数据库规划,建表语句,程序中SQL语句以供审核.以便DBA合理建库,优化数据表,索引以及优化SQL

(2) 所有的建表操作需要确定建立哪些索引后才可以建表上线
(3) 禁止私自进行批量导入、导出数据,必须提前通知DBA进行相关操作
(4) 新系统数据库和表,高并发大数据量复杂业务场景设计.
(5) 推广活动或上线新功能必须提前通知技术团队进行流量评估和支持
(6) 不在业务高峰期批量更新、使用大查询操作数据库

 

五、安全规范

(1)严禁使用公网IP连接数据库
(2)生产、开发、测试环境分离,保证基本配置参数一致
(3)禁止线下测试、线下开发环境直连线上数据库

 

六、附录

附录一:MYSQL关键字

ADD

ALL

ALTER

ANALYZE

AND

AS

ASC

ASENSITIVE

BEFORE

BETWEEN

BIGINT

BINARY

BLOB

BOTH

BY

CALL

CASCADE

CASE

CHANGE

CHAR

CHARACTER

CHECK

COLLATE

COLUMN

CONDITION

CONNECTION

CONSTRAINT

CONTINUE

CONVERT

CREATE

CROSS

CURRENT_DATE

CURRENT_TIME

CURRENT_TIMESTAMP

CURRENT_USER

CURSOR

DATABASE

DATABASES

DAY_HOUR

DAY_MICROSECOND

DAY_MINUTE

DAY_SECOND

DEC

DECIMAL

DECLARE

DEFAULT

DELAYED

DELETE

DESC

DESCRIBE

DETERMINISTIC

DISTINCT

DISTINCTROW

DIV

DOUBLE

DROP

DUAL

EACH

ELSE

ELSEIF

ENCLOSED

ESCAPED

EXISTS

EXIT

EXPLAIN

FALSE

FETCH

FLOAT

FLOAT4

FLOAT8

FOR

FORCE

FOREIGN

FROM

FULLTEXT

GOTO

GRANT

GROUP

HAVING

HIGH_PRIORITY

HOUR_MICROSECOND

HOUR_MINUTE

HOUR_SECOND

IF

IGNORE

IN

INDEX

INFILE

INNER

INOUT

INSENSITIVE

INSERT

INT

INT1

INT2

INT3

INT4

INT8

INTEGER

INTERVAL

INTO

IS

ITERATE

JOIN

KEY

KEYS

KILL

LABEL

LEADING

LEAVE

LEFT

LIKE

LIMIT

LINEAR

LINES

LOAD

LOCALTIME

LOCALTIMESTAMP

LOCK

LONG

LONGBLOB

LONGTEXT

LOOP

LOW_PRIORITY

MATCH

MEDIUMBLOB

MEDIUMINT

MEDIUMTEXT

MIDDLEINT

MINUTE_MICROSECOND

MINUTE_SECOND

MOD

MODIFIES

NATURAL

NOT

NO_WRITE_TO_BINLOG

NULL

NUMERIC

ON

OPTIMIZE

OPTION

OPTIONALLY

OR

ORDER

OUT

OUTER

OUTFILE

PRECISION

PRIMARY

PROCEDURE

PURGE

RAID0

RANGE

READ

READS

REAL

REFERENCES

REGEXP

RELEASE

RENAME

REPEAT

REPLACE

REQUIRE

RESTRICT

RETURN

REVOKE

RIGHT

RLIKE

SCHEMA

SCHEMAS

SECOND_MICROSECOND

SELECT

SENSITIVE

SEPARATOR

SET

SHOW

SMALLINT

SPATIAL

SPECIFIC

SQL

SQLEXCEPTION

SQLSTATE

SQLWARNING

SQL_BIG_RESULT

SQL_CALC_FOUND_ROWS

SQL_SMALL_RESULT

SSL

STARTING

STRAIGHT_JOIN

TABLE

TERMINATED

THEN

TINYBLOB

TINYINT

TINYTEXT

TO

TRAILING

TRIGGER

TRUE

UNDO

UNION

UNIQUE

UNLOCK

UNSIGNED

UPDATE

USAGE

USE

USING

UTC_DATE

UTC_TIME

UTC_TIMESTAMP

VALUES

VARBINARY

VARCHAR

VARCHARACTER

VARYING

WHEN

WHERE

WHILE

WITH

WRITE

X509

XOR

YEAR_MONTH

ZEROFILL

    

 

附录二:

数字型

 

 

 

 

类型

大小

范围(有符号)

范围(无符号)

用途

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)

大整数值

BIGINT

8 字节

(-9 233 372 036 854 775 808,9 223 372 036 854 775 807)

(0,18 446 744 073 709 551 615)

极大整数值

FLOAT

4 字节

(-3.402 823 466 E+38,1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38)

0,(1.175 494 351 E-38,3.402 823 466 E+38)

单精度

浮点数值

DOUBLE

8 字节

(1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)

0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)

双精度

浮点数值

DECIMAL

对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2

依赖于M和D的值

依赖于M和D的值

小数值

字符类型

 

 

 

 

类型

大小

描述

 

 

CHAR

0-255字符

定长字符串

VARCHAR

0-65536字符

变长字符串

TINYBLOB

0-255字符

不超过 255 个字符的二进制字符串

TINYTEXT

0-255字符

短文本字符串

BLOB

0-65 535字符

二进制形式的长文本数据

TEXT

0-65 535字符

长文本数据

MEDIUMBLOB

0-16 777 215字符

二进制形式的中等长度文本数据

MEDIUMTEXT

0-16 777 215字符

中等长度文本数据

LOGNGBLOB

0-4 294 967 295字符

二进制形式的极大文本数据

LONGTEXT

0-4 294 967 295字符

极大文本数据

时间类型

 

 

 

 

类型

大小

范围

格式

用途

(字节)

DATE

3

1000-01-01/9999-12-31

YYYY-MM-DD

日期值

TIME

3

'-838:59:59'/'838:59:59'

HH:MM:SS

时间值或持续时间

YEAR

1

1901/2155

YYYY

年份值

DATETIME

8

1000-01-01 00:00:00/9999-12-31 23:59:59

YYYY-MM-DD HH:MM:SS

混合日期和时间值

TIMESTAMP

8

1970-01-01 00:00:00/2037 年某时

YYYYMMDD HHMMSS

混合日期和时间值,时间戳

这篇关于Mysql建表规范备忘录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/996155

相关文章

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

mysql外键创建不成功/失效如何处理

《mysql外键创建不成功/失效如何处理》文章介绍了在MySQL5.5.40版本中,创建带有外键约束的`stu`和`grade`表时遇到的问题,发现`grade`表的`id`字段没有随着`studen... 当前mysql版本:SELECT VERSION();结果为:5.5.40。在复习mysql外键约

SQL注入漏洞扫描之sqlmap详解

《SQL注入漏洞扫描之sqlmap详解》SQLMap是一款自动执行SQL注入的审计工具,支持多种SQL注入技术,包括布尔型盲注、时间型盲注、报错型注入、联合查询注入和堆叠查询注入... 目录what支持类型how---less-1为例1.检测网站是否存在sql注入漏洞的注入点2.列举可用数据库3.列举数据库

Mysql虚拟列的使用场景

《Mysql虚拟列的使用场景》MySQL虚拟列是一种在查询时动态生成的特殊列,它不占用存储空间,可以提高查询效率和数据处理便利性,本文给大家介绍Mysql虚拟列的相关知识,感兴趣的朋友一起看看吧... 目录1. 介绍mysql虚拟列1.1 定义和作用1.2 虚拟列与普通列的区别2. MySQL虚拟列的类型2

mysql数据库分区的使用

《mysql数据库分区的使用》MySQL分区技术通过将大表分割成多个较小片段,提高查询性能、管理效率和数据存储效率,本文就来介绍一下mysql数据库分区的使用,感兴趣的可以了解一下... 目录【一】分区的基本概念【1】物理存储与逻辑分割【2】查询性能提升【3】数据管理与维护【4】扩展性与并行处理【二】分区的

MySQL中时区参数time_zone解读

《MySQL中时区参数time_zone解读》MySQL时区参数time_zone用于控制系统函数和字段的DEFAULTCURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型... 目录前言1.时区参数影响2.如何设置3.字段类型选择总结前言mysql 时区参数 time_zon

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3