MySQL学习笔记5

86 阅读4分钟

数据类型的选择

如果需要学习数据库设计方面的基础知识,建议阅读Clare Churcher的Beginning Database Design。

不管存储哪种类型的数据,下面几个简单的原则都有助于做出更好的选择。

更小的通常更好

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

如果无法确定哪个数据类型是最好的,就选择你认为不会超过范围的最小类型。

简单就好

应该使用MySQL内建的类型而不是字符串来存储日期和时间,另外一个是应该用整型存储IP地址。

尽量避免NULL

通常情况下最好指定列为NOT NULL ,除非真的需要存储NULL 值。

如果查询中包含可为NULL 的列,对MySQL来说更难优化,因为可为NULL 的列使得索引、索引统计和值比较都更复杂。

各数据类型注意事项

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用DECIMAL ——例如存储财务数据。

但在数据量比较大的时候,可以考虑使用BIGINT 代替DECIMAL ,将需要存储的货币单位根据
小数的位数乘以相应的倍数即可。假设要存储财务数据精确到万分之一分,则可以把所有金额乘以一百万,然后将结果存储在BIGINT 里,这样可以同时避免浮点存储计算不精确DECIMAL 精确计算代价高的问题。

VARCHAR 节省了存储空间,所以对性能也有帮助。但是,由于行是变长的,在UPDATE 时可能使行变得比原来更长,这就导致需要做额外的工作。

下面这些情况下使用VARCHAR 是合适的:字符串列的最大长度比平均长度大很多;列的更新很少,所以碎片不是问题;使用了像UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储。
在5.0或者更高版本,MySQL在存储和检索时会保留VARCHAR类型数据的末尾空格。但在4.1或更老的版本,MySQL会剔除末尾空格。

当存储CHAR 值时,MySQL会删除所有的末尾空格。

CHAR 适合存储很短的字符串,或者所有值都接近同一个长度。对于经常变更的数据,CHAR 也比VARCHAR 更好,因为定长的CHAR 类型不容易产生碎片。

BLOB 和TEXT 都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。MySQL把每个BLOB 和TEXT 值当作一个独立的对象处理。

MySQL能存储的最小时间粒度为秒。

MySQL提供两种相似的日期类型:DATETIME 和TIMESTAMP 

DATETIME

从1001年到9999年,精度为秒。它把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,与时区无关。使用8个字节的存储空间。

TIMESTAMP

TIMETAMP 类型保存了从1970年1月1日午夜(格林尼治标准时间)以来的秒数,它和UNIX时间戳相同。TIMESTAMP 只使用4个字节的存储空间。只能表示从1970年到2038年

如果在多个时区存储或访问数据,TIMESTAMP 和DATETIME 的行为将很不一样。前者提供的值与时区有关系,后者则保留文本表示的日期和时间。

除了特殊行为之外,通常也应该尽量使用TIMESTAMP ,因为它比DATETIME 空间效率更高。

可以使用BIGINT 类型存储微秒级别的时间截,或者使用DOUBLE 存储秒之后的小数部分。

MySQL把BIT 当作字符串类型,而不是数字类型。当检索BIT(1) 的值时,结果是一个包含二进制0或1值的字符串,而不是ASCII码的“0”或“1”。在数字上下文的场景中检索时,结果将是位字符串转换成的数字。

应该谨慎使用BIT类型。

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

如果存储UUID值,则应该移除“-”符号;或者更好的做法是,用UNHEX() 函数转换UUID值为16字节的数字,并且存储在一个BINARY(16) 列中。检索时可以通过HEX() 函数来格式化为十六进制格式。

应该用无符号整数存储IP地址。MySQL提供INET_ATON() 和INET_NTOA() 函数在这两种表示方法之间转换。