改它
?
TIMESTAMP类型适合用来记录数据的最后修改时间,因为只要你更改了记录中其他字段的值,timestamp字段的值都会被自动更新
4、选择标识符
?
?
为标识列选择好的数据类型非常重要,你可能会更多地用它们和其他列做比较,还可能把它们用作其它表的外键,因为选择标识符列选择数据类型的时候,你也可能是在为相关的表选择数据类型。
?
当为标识符列选择数据类型的时候,不仅要考虑存储类型,还要考虑MYSQL如何对它们进行计算和比较。例如:MYSQL会在内部把ENUM和SET类型保存为整数,但是在比较的时候把它们转换为字符串。
?
一旦选择了数据类型,要确保在相关表中使用同样的类型。类型之前要精确匹配,包括诸如UNSIGNED这样的属性。混合不同的数据类型会导致性能问题,即使没有性能问题,隐式的类型转换也能导致难以察觉的错误,在你已经忘记了自己是在对不同类型做比较的时候,这些错误就会突然出现。
?
选择最小的数据类型能表明所需值的范围,并且为将来留出增长的空间。例如,如果用PORVINCE_ID来表示中国的省份,那么我们知道它不会产成千上万个值,因类就没有必要使用INT,用TINYINT就足够了,它比INT小3个节字,如果把一个表的主键是TINYINT,而另一个表以INT作为外键,那么就会造成较大的性能差距。
?
整数通常是标识符的最佳选择,因为它速度快,并且能使用AUTO_INCREMENT。
?
ENUM和SET通常不合适用作标识符,尽管它适合用来做静态的,包含了状态和“类型”和值的“定义表”。
?
ENUM和SET列适合用来性别、国家、省份这些固定不变的信息。
?
要尽可能的避免使用字符串来做标识符,因为它们占用了很多空间并且通常比整数类型要慢,特别注意不要在MYISAM表上使用字符串标识符。MYISAM默认情况下为字符串使用了压缩索引,这使查找更为缓慢。
?
MYISAM使用前缀压缩来减小索引大小,默认情况下会压缩字符串,也可以压缩整数
?
可以使用CREATE TABLE时用PACK_KEYS控制索引压缩的方式。
?
PACK_KEYS在MYSQL手册中如下描述:
?
如果您希望索引更小,则把此选项设置为1。这样做通常使更新速度变慢,同时阅读速度加快。把选项设置为0可以取消所有的关键字压缩。把此选项设置为DEFAULT时,存储引擎只压缩长的CHAR或VARCHAR列(仅限于MYISAM)。
?
如果您不使用PACK_KEYS,则默认操作是只压缩字符串,但不压缩数字。如果您使用PACK_KEYS=1,则对数字也进行压缩。
?
5、特殊类型的数据
?
一些数据类型没有直接对应的内建数据类型,精度低于秒的时间戳就是一个例子,另一个例子就是IP地址,人们通常使用varchar(15)来保存IP地址。但是,IP地址实际上是无符号的32位整数,而不是字符串。使用小数点来进行分纯粹是为了增加它的可读性。在实际使用时应用用无符号整数来存储IP地址。MySQL提供了INET_ATON()和INET_NTOA()函数在IP地址和整数之前转换。
?
数据库操作中最为耗时的操作就是 IO 处理,大部分
数据库操作 90% 以上的时间都花在了 IO 读写上面。所以尽可能减少 IO 读写量,可以在很大程度上提高数据库操作的性能。
?
我们无法改变数据库中需要存储的数据,但是我们可以在这些数据的存储方式方面花一些心思。下面的这些关于字段类型的优化建议主要适用于记录条数较多,数据量较大的场景,因为精细化的数据类型设置可能带来维护成本的提高,过度优化也可能会带来其他的问题?
?
字符编码
?
字符集直接决定了数据在MySQL中的存储编码方式,由于同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助我们尽可能减少数据量,进而减少IO操作次数。
?
纯拉丁字符能表示的内容,没必要选择 latin1 之外的其他字符编码,因为这会节省大量的存储空间
?
如果我们可以确定不需要存放多种语言,就没必要非得使用UTF8或者其他UNICODE字符类型,这回造成大量的存储空间浪费
?
MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率
?
适当拆分
?
有些时候,我们可能会希望将一个完整的对象对应于一张数据库表,这对于应用
程序开发来说是很有好的,但是有些时候可能会在性能上带来较大的问题。
?
当我们的表中存在类似于 TEXT 或者是很大的 VARCHAR类型的大字段的时候,如果我们大部分访问这张表的时候都不需要这个字段,我们就该义无反顾的将其拆分到另外的独立表中,以减少常用数据所占用的存储空间。这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理 IO 次数,也能大大提高内存中的缓存命中率。
?
上面几点的优化都是为了减少每条记录的存储空间大小,让每个
数据库中能够存储更多的记录条数,以达到减少 IO 操作次数,提高缓存命中率。下面这个优化建议可能很多开发人员都会觉得不太理解,因为这是典型的反范式设计,而且也和上面的几点优化建议的目标相违背。
?
适度冗余
?
为什么我们要冗余?这不是增加了每条数据的大小,减少了每个数据块可存放记录条数吗?
?
确实,这样做是会增大每条记录的大小,降低每条记录中可存放数据的条数,但是在有些场景下我们仍然还是不得不这样做:
?
被频繁引用且只能通过 Join 2张(或者更多)大表的方式才能得到的独立小字段
?
这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的 IO,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新