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类型,因为他的存储空间只需要三个字节,比TIMESTAMP还少。不建议通过INT存储一种类型unix timestamp 值,因为太不直观,会给维护带来不必要的麻烦,同时也不会带来任何好处。
(6). 其他类型
6.1选择标识符
能满足值范围的需求, 在预留未来增长空间的前提下, 应选择最小数据类型。
整数类型
标识列通常是整数的最佳选择, 因为它们使用,因为它们可以使用AUTO_INCREMENT。
ENUM和SET类型
对于标识列,EMUM和SET类型通常是不好的选择, 虽然对于某些静态,只包括固定状态或类型 ”定义表” 可能没问题。ENUM和SET列适用于存储固定信息, 例如,状态有序, 产品类型、 人的性别。
字符串类型
如果可能, 应避免使用字符串类型作为标识列, 因为它们消耗空间, 而且通常比数字类型慢。
对于完全 “随机” 还需要多注意字符串, 例如 MDS() 、 SHAl() 或者 UUID() 字符串。 这些函数产生的新值将在很大的空间内任意分布, 这会导致 INSERT 以及一些SELECT句子变慢了。如果存储。 UUID 值, 则应该移除 "-"符号。
6.2特殊类型数据
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只能一个