mysql表设计

1. 选择存储引擎

在表结构设计中,首先我们就要选择一个合适的存储引擎,如果需要事务操作,那就选InnoDB存储引擎,如果主要要求读性能高,可用MyISAM存储引擎,如果你不知道如何选择,那就用InnoDB存储引擎。

目前广泛使用的是MyISAM和InnoDB两种引擎:

1. MyISAM

MyISAM引擎是MySQL 5.1及之前版本的默认引擎,它的特点是:

不支持行锁,读取时对需要读到的所有表加锁,写入时则对表加排它锁
不支持事务
不支持外键
不支持崩溃后的安全恢复
在表有读取查询的同时,支持往表中插入新纪录
支持BLOB和TEXT的前500个字符索引,支持全文索引
支持延迟更新索引,极大提升写入性能
对于不会进行修改的表,支持压缩表,极大减少磁盘空间占用
2. InnoDB

InnoDB在MySQL 5.5后成为默认索引,它的特点是:

支持行锁,采用MVCC来支持高并发
支持事务
支持外键
支持崩溃后的安全恢复
不支持全文索引

2.表结构设计

2. 表结构设计
范式设计,消除冗余
数据库范式是确保数据库结构合理,满足各种查询需要、避免数据库操作异常的数据库设计方式。满足范式要求的表,称为规范化表,范式产生于20世纪70年代初,一般表设计满足前三范式就可以,在这里简单介绍一下前三范式

通俗的三范式解释:

  第一范式:属性(字段)的原子性约束,要求属性具有原子性,不可再分割;
  第二范式:记录的惟一性约束,要求记录有惟一标识,每条记录需要有一个属性来做为实体的唯一标识。
  第三范式:属性(字段)冗余性的约束,即任何字段不能由其他字段派生出来,在通俗点就是:主键没有直接关系的数据列必须消除(消除的办法就是再创建一个表来存放他们,当然外键除外)

如果数据库设计达到了完全的标准化,则把所有的表通过关键字连接在一起时,不会出现任何数据的复本(repetition)。标准化的优点是明显的,它避免了数据冗余,自然就节省了空间,也对数据的一致性(consistency)提供了根本的保障,杜绝了数据不一致的现象,同时也提高了效率。

反范式设计,适当冗余
数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点 

满足范式的表一定是规范化的表,但不一定是最佳的设计。

很多情况下会为了提高数据库的运行效率,常常需要降低范式标  准:适当增加冗余,达到以空间换时间的目的。比如我们有一个表,产品名称,单价,库存量,总价值。这个表是不满足第三范式的,因为“总价值”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“总价值”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。合理的冗余可以分散数据量大的表的并发压力,也可以加快特殊查询的速度,冗余字段可以有效减少数据库表的连接,提高效率。

3. 主键

主键:根据第二范式,需要有一个字段去标识这条记录,主键无疑是最好的标识,需要满足唯一性、非空性,但是很多表也不一定需要主键,但是对于数据量大,查询频繁的数据库表,一定要有主键,主键可以增加效率、防止重复等优点。

主键的选择也比较重要,一般选择长度小的键,小的键的比较速度快,同时小的键可以使主键的B树结构的层次更少。
主键的选择还要注意组合主键的字段次序,对于组合主键来说,不同的字段次序的主键的性能差别可能会很大,一般应该选择重复率低、单独或者组合查询可能性大的字段放在前面。

4. 选择数据类型

MySQL支持的数据类型非常多, 选择正确的数据类型对于获得高性能至关重要。

更小的通常更好
更小的数据类型通常更快, 因为它们占用更少的磁盘、 内存和CPU缓存, 并且处理时需要的CPU周期也更少。

简单就好
简单数据类型的操作通常需要更少的CPU周期。 例如, 整型比字符操作代价更低, 因为字符集和校对规则(排序规则 )使字符比较比整型比较更复杂。

尽量避免NULL
如果查询中包含可为NULL 的列, 对MySQL来说更难优化, 因为可为NULL 的列使得索引、 索引统计和值比较都更复杂。 可为NULL的列会使用更多的存储空间, 在MySQL里也需要特殊处理。 当可为NULL的列被索引时, 每个索引记录需要一个额外的字节, 在MyISAM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。当然也有例外, 例如InnoDB 使用单独的位 (bit) 存储NULL值, 所以对于稀疏数据有很好的空间效率。

数据类型尽量用数字型,数字型的比较比字符型的快很多
 

(1). 整数类型
有两种类型的数字:整数 (whole number) 和实数 (real number) 。 如果存储整数, 可以使用这几种整数类型:TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT。分别使用8,16, 24, 32, 64位存储空间。

整数类型有可选的 UNSIGNED属性,表示不允许负值,这大致可以使正数的上限提高一倍。 

有符号和无符号类型使用相同的存储空间,并具有相同的性能, 因此可以根据实际情况选择合适的类型。

MySQL 可以为整数类型指定宽度, 例如 INT(11), 对大多数应用这是没有意义的:它不会限制值的合法范围,只是规定了MySQL 的一些交互工具(例如 MySQL 命令行客户端)用来显示字符的个数。 对于存储和计算来说, INT(1) 和 INT(20) 是相同的。

(2). 实数类型
实数是带有小数部分的数字。 然而, 它们不只是为了存储小数部分,也可以使用DECIMAL 存储比 BIGINT 还大的整数。

FLOAT和DOUBLE类型支持使用标准的浮点运算进行近似计算。

DECIMAL类型用于存储精确的小数。

浮点和DECIMAL类型都可以指定精度。 对于DECIMAL列, 可以指定小数点前后所允许的最大位数。这会影响列的空间消耗。

有多种方法可以指定浮点列所需要的精度, 这会使得MySQL选择不同的数据类型,或者在存储时对值进行取舍。 这些精度定义是非标准的,所以我们建议只指定数据类型,不指定精度。

浮点类型在存储同样范围的值时, 通常比DECIMAL使用更少的空间。FLOAT使用4个字节存储。DOUBLE占用8个字节,相比FLOAT有更高的精度和更大的范围。和整数类型一样, 能选择的只是存储类型; MySQL使用DOUBLE作为内部浮点计算的类型。

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用DECIMAL。但在数据最比较大的时候, 可以考虑使用BIGINT代替DECIMAL, 将需要存储的货币单位根据小数的位数乘以相应的倍数即可。

(3). 字符串类型
VARCHAR用于存储可变⻓字符串,长度支持到65535,需要使用1或2个额外字节记录字符串的长度,适合:字符串的最大⻓度比平均⻓度⼤很多;更新很少

CHAR:定⻓,⻓度范围是1~255,适合:存储很短的字符串,或者所有值接近同一个长度;经常变更

使用VARCHAR(5)和VARCHAR(200)存储'hello'的空间开销是一样的。 那么使用更短的列有什么优势吗?

事实证明有很大的优势。 更长的列会消耗更多的内存, 因为MySQL通常会分配固定大小的内存块来保存内部值。 尤其是使用内存临时表进行排序或操作时会特别糟糕。 在利用磁盘临时表进行排序时也同样糟糕。

所以最好的策略是只分配真正需要的空间。

(4). BLOB和TEXT类型
BLOB和 TEXT都是为存储很大的数据而设计的字符串数据类型, 分别采用二进制和字符方式存储 。

与其他类型不同, MySQL把每个BLOB和TEXT值当作一个独立的对象处理。存储引擎在存储时通常会做特殊处理。 当BLOB和TEXT值太大时,InnoDB会使用专门的 “外部“存储区域来进行存储, 此时每个值在行内需要1 - 4个字节存储 存储区域存储实际的值。

BLOB 和 TEXT 之间仅有的不同是 BLOB 类型存储的是二进制数据, 没有排序规则或字符集, 而TEXT类型有字符集和排序规则

(5). 日期和时间类型
尽量使用TIMESTAMP类型, 因为其存储空间只需要 DATETIME 类型的一半。对于只需要精确到某一天的数据类型,建议使用DATE类型,因为他的存储空间只需要3个字节,比TIMESTAMP还少。不建议通过INT类型类存储一个unix timestamp 的值,因为这太不直观,会给维护带来不必要的麻烦,同时还不会带来任何好处。
 

(6). 其他类型
6.1选择标识符

在可以满足值的范围的需求, 井且预留未来增长空间的前提下, 应该选择最小的数据类型。

整数类型

整数通常是标识列最好的选择, 因为它们很快并且可以使用AUTO_INCREMENT。

ENUM和SET类型

对于标识列来说,EMUM和SET类型通常是一个糟糕的选择, 尽管对某些只包含固定状态或者类型的静态 ”定义表” 来说可能是没有问题的。ENUM和SET列适合存储固定信息, 例如有序的状态、 产品类型、 人的性别。

字符串类型

如果可能, 应该避免使用字符串类型作为标识列, 因为它们很消耗空间, 并且通常比数字类型慢。

对于完全 “随机” 的字符串也需要多加注意, 例如 MDS() 、 SHAl() 或者 UUID() 产生的字符串。 这些函数生成的新值会任意分布在很大的空间内, 这会导致 INSERT 以及一些SELECT语句变得很慢。如果存储 UUID 值, 则应该移除 "-"符号。

6.2特殊类型数据

某些类型的数据井不直接与内置类型一致。 低千秒级精度的时间戳就是一个例子,另一个例子是以个1Pv4地址,人们经常使用VARCHAR(15)列来存储IP地址,然而, 它们实际上是32位无符号整数, 不是字符串。用小数点将地址分成四段的表示方法只是为了让人们阅读容易。所以应该用无符号整数存储IP地址。MySQL提供INET_ATON()和INET_NTOA()函数在这两种表示方法之间转换。

5.合适的索引

索引是一个表优化的重要指标,在表优化中占有极其重要的成分,另外单独讲。

6.添加注释

添加注释,其中包括表注释,字段注释,对后期表结构的维护非常重要。

附所有字段类型:

(一)整型数值:

整数类型 字节数 最小值 ~ 最大值
tinyint 1 -128~127 或 0-255
smallint 2 -32768~32767 或 0~65535
mediumint 3 -8388608~8388607 或 0~1677215
int 4 -2147483648~2147483647 或 0~4294967295
bigint 8 -9223372036854775808~9223372036854775807 或 0~18446744073709551615

(二)浮点数类型

浮点数类型 字节数 最小值 ~ 最大值
double 4 ±1.175494351E-38 ~ ± 3.402823466E+38
double 8 ±2.2250738585072014E-308 ~ ±1.7976931348623157E+308

(三)定点数类型

定点数类型 字节数 最小值 ~ 最大值
dec(m,d) m+2 最大取值范围与double相同,给定decimal的有效值取值范围由m和d决定

(四)位类型

位类型 字节数 最小值 ~ 最大值
bit(m) 1~8 bit(1) ~ bit(64)

(五)日期时间类型

时间日期类型 字节数 最小值 ~ 最大值
date 4 1000-01-01 ~ 9999-12-31
datetime 8 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
timestamp 4 19700101080001 ~ 2038年某个时刻
time 3 -838:59:59 ~ 838:59:59
year 1 1901 ~ 2155

(六)字符串类型:

字符串类型 字节数 取值范围
char(m) m m为0 ~ 255之间的整数
varchar(m) 值长度+1 m为0~65535之间的整数
tinytext 值长度+2 允许长度0~255字节
text 值长度+2 允许长度0~65535字节
mediumtext 值长度+3 允许长度0~167772150字节
longtext 值长度+3 允许长度0~4294967295字节
binary(m) m 允许0~m个字节定长的字符串
varbinary(m) 值长度+1 允许0~m个字节变长的字符串
tinyblob 值长度+1 允许长度0~255字节
blob 值长度+2 允许长度0~65535字节
mediumblob 值长度+3 允许长度0~167772150字节
longblob 值长度+4 允许长度0~4294967295字节
enum 1或2 1255个成员需要1个字节存;25565535个成员,2个字节存
set 1/2/3/4/8 类似enum,set一次可以选取多个成员,而enum只能一个
原文地址:https://www.cnblogs.com/wangxiaosai/p/14181076.html