数据库开发规范以及优化(MySql)

建表时需考虑的事情

在实际的业务场景中,利用关系表来构建整个业务需求,那么我们需要考虑的是
范式规范(1NF,2NF,3NF,BCNF,4NF,5NF);
表之间的关系(一对一,一对多,多对多);
表用途(数据表,配置表);
数据库级别配置
表字段
索引使用

范式规范

1NF:关系中的每个属性都不可再分。

1NF是所有关系型数据库的最基本要求,不符合1NF的关系表是无法在数据库中建立的。但是只满足1NF的表数据冗余过大,而且会存在插入异常删除异常修改异常的问题。我们举一个金融系统中贷款申请的一个实际业务场景来说,现在设计一个贷款申请表,该表符合1NF

贷款申请表

数据冗余过大:贷款渠道描述,贷款产品描述,所属额度描述,这三个字段完全是冗余字段。

插入异常:如果我们想新增一个贷款渠道,但是没有人从这个渠道贷款,我们便无法插入这个渠道。
删除异常:我们要删除李四的贷款信息,那么对应的贷款产品p2,也被删除了。
修改异常:我们要修改张三的贷款产品的话,那么产品对应关系也被修改了。
总之一句话,1NF下的表,牵一发动全身。

2NF和3NF:消除了非主属性对于码的部分函数依赖(2NF)和传递函数依赖(3NF)

首先,理清概念
完全函数依赖:
部分函数依赖:
传递函数依赖:
码:设 K 为某表中的一个属性或属性组,若除 K 之外的所有属性都完全函数依赖于 K(这个“完全”不要漏了),那么我们称 K 为候选码,简称为。在实际中我们通常可以理解为:假如当 K 确定的情况下,该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码。一张表中可以有超过一个码。(实际应用中为了方便,通常选择其中的一个码作为主码

表之间的关系

如果你设计的表符合BCNF范式的话,那么对于一对一,一对多,多对多这些表之间的关系就能理解了。之所以表之间有这些关系,就是为了让表符合范式规范。

一对一关系

实际情况中,我们只有在垂直分表中使用。表中字段数过多,可以分为热点字段和非热点字段,我们可以根据这个,利用主键,将这些字段拆分到不同的表中。

一对多关系

实现2NF和3NF规范,我们就要用到一对多关系。

多对多关系

要想实现多对多关系,就需要引入一张中间表,中间表中的两个字段存储另外两张表的主属性(主键)

表用途

数据表

数据表(流水表)是有状态的,多笔业务之间没有关联,会有大量insert,update和查询操作。是我们优化的重点对象。

配置表

一些业务数据的配置,特点是数据量较小,而且结构简单,一般为静态数据,变化频率很低,但CRUD的场景比较多。即使出现大量CRUD,但数据量小,其实影响不大。

其实配置表和数据表是一对多主外键关联关系。但我们会面临一个问题,就是配置表中的配置不是一成不变的,那这个时候数据表中外键关联的该项配置就跟着变了。其实到底变还是不变是根据实际业务需求来看的。根据后视镜原则,我思考了一个比较好的方案,能够满足表范式规范,又能回溯数据。
配置表:(id,code,version,status...业务相关配置)
其中id为表主键,唯一;code为业务编码,可以唯一标识一个业务配置;version为该业务版本的版本号(code+version为主属性,可以唯一标识一笔数据)stats为生效失效状态(code+status也为主属性,也可以唯一标识一笔数据)。当修改某一项配置的时候不进行update,而是insert一条新的数据,只是version+1,然后上一笔失效。
数据表:(id,foreign1,foreign2,...其他数据)
id为主键;对于外键关联配置表的foreign,我们到底选配置表的id,还是code+status(或者是code+version)?如果我们要求数据表中配置项不需要关联最新配置,而是保留当时配置现场数据,那么我们就选id为foreign;如果要求实时最新配置数据的时候,我们就要选择code+status为foreign。

数据库级别配置

存储引擎的选择

InnoDB 存储引擎支持事务,一般业务系统特别是交易类系统,都需要事务支持,所以只能选InnoDB。MyISAM特点是访问速度快,如果事务没有要求,但有大量insert和select操作,可以选择。

字符集选择

从应用(前后端),到数据库,我们都应统一字符集,这样可以避免字符集转化带来的性能损耗。推荐都使用UTF-8

事务隔离级别

MySql默认的隔离级别是Repeatable-Read,但建议改为Read-Committed,更适合OLTP 业务场景。

表字段

1.定长字符类型使用char(),但对于InnoDB存储引擎,使用varchar要更好。
2.变长字符类型使用varchar(),但对于变长字符应该有个预估,不能统一初始化为varchar(500)等。
3.整型定义中无需定义显示宽度,比如:使用 INT,而不是 INT(4)。
4.存储精确浮点数必须使用 DECIMAL 替代 FLOAT 和 DOUBLE。
5.尽可能不使用 TEXT、BLOB 类型,如果必须使用,建议将过大字段或是不常用的描述型较大字段拆分到其他表中;另外,禁止用数据库存储图片或文件。数据库处理 TEXT、BLOB 类型相当耗时,特别是进行删除操作。
6.日期类型选择,如果是年,用year(4);如果是年月日,用DATE;如果是年月日时分秒,用DATETIME。建议时间字段使用应用生成,而不是数据库。
7.建议字段定义为 NOT NULL。特别是索引列,因为MySQL对于null的列使得索引,索引统计和值的比较都更复杂。
8.每个字段都要有注释

索引使用

对于不同的存储引擎,支持的索引类型也不一样,现在只讨论InnoDB的B+树索引全文索引HASH索引。但由于90%的情况都是使用B+树索引,所以我们先讨论。
首先现解释几个概念
B+树:
是一个特殊的查找树,本文不展开篇幅进行解释,但可以去看程序员小灰讲解的B+树,里面讲解了什么是B+树,以及为什么数据库索引使用B+树。
聚集索引:
1.一张表有且只有一个聚集索引。
2.如果表有主键,按表的主键构造一个B+树,叶子节点存放表中行记录数据,称为数据叶,数据页以双向链表进行连接,数据页逻辑有序。
3.如果没有主键,MySQL也会建立一个聚集索引,但索引列是数据库生成的。
非聚集索引(辅助索引):
1.一张表可以有多个。
2.叶子节点存放的是一个指向聚集索引的指针,通过该表的聚集索引查询到数据页,返回查询的行数据,即使用非聚集索引存在二次查询问题。
Cardinality(索引基数):
索引列中不重复记录数量的预估值。如果记录都不重复(例如唯一约束字段,那么基数就为1)
单列索引:
定义一个索引对应一个列。
联合索引:
定义一个索引对应多个列。联合索引我们要考虑最左原则,举例说明,建立一个联合索引indx_abc(a,b,c),where a=XX;where a=XX and b=XX;where a=XX and b=XX and c=XX;都是可以使用到该索引的,但是where b=XX;where c=XX;where b=XX and c=XX是不能使用到索引的。

那么总结一下我们使用索引的原则:
1.我们建表的时候一定要指定主键,而且主键最好使用连续的数值类型,不要使用UUID。
2.要考虑数据列的Cardinality(索引基数),如果过小,则想想是否必要建立索引。
3.根据业务场景查询的情况,即where后的条件,来思考如何建立索引,是建立单列索引还是联合索引。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容

  • 数据库开发规范1. 数据库命名规范前缀对象前缀命名: 前缀命名一般用小写表的前缀: 业务模块组名前缀存储过程前缀:...
    PowerYangSoft阅读 2,431评论 0 8
  • 回顾 字段类型(列类型):数值型,时间日期型和字符串类型 数值型:整型和小数型(浮点型和定点型) 时间日期型:da...
    翊溪阅读 924评论 0 0
  • 索引 数据库中的查询操作非常普遍,索引就是提升查找速度的一种手段 索引的类型 从数据结构角度分 1.B+索引:传统...
    一凡呀阅读 2,853评论 0 8
  • 命名规范 库名、表名、字段名必须使用小写字母,并采用下划线分割MySQL有配置参数lower_case_table...
    swoft_阅读 617评论 0 0
  • 数据库的基本是概念名词解释: 数据库名词解释 元组:可以理解为表的每一行就是一个元组 候选码:若关系中的某一属性组...
    杰伦哎呦哎呦阅读 1,099评论 0 6