1.优先使用符合业务需要的最小的数据类型
1.1 将ip用UNSIGNED INT存:内置函数INET_ATON(字符串)和INTE_NTOA(整数)分别是点分十进制字符串和整数的转换函数
1.2 非负数用无符号类型(比如前面ip值对应的数字一定为正,所以用的数据类型为无符号整形,ip是8为*4=32位,也就是而int也正好是32位,而ip对应的全是正的,如果是用有符号int存的话那就只能表示一半,所以要用无符号int)
1.3不要用TEXT,BLOB,或者把他们都分离到单独的扩展表中
2.使用枚举(ENUM)类型代替字符串
2.1枚举类型在内部实际存储为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的“查找表”
2.2可以通过SELECT 枚举类型的列+0 FROM 表名来隐式转换来看到具体的整数
2.3不要用数字作为ENUM枚举常量(如ENUM('1','2','3')),这种双重性容易导致混乱
2.4枚举字段是按照内部存储的整数而不是定义的字符串进行排序,但可以用FIELD()函数显式地指定排序顺序如:SELECT e FROM enum_test ORDER BY FIELD(e,'apple','dog','fish');(e是枚举字段),不过这会导致MySQL无法利用索引消除排序(什么叫索引消除排序呢:就是说在查询中对索引字段排序,那这时其实是不用在执行一遍排序算法的,因为B+树保存索引,而B+树中维护的信息可以很快得到索引的顺序,相当于索引本身就是以有序的状态存储的。但这里你把他的原来的排序规则打破了,也就是显式地指定了排序顺序,那也就是相对于你规定的排序规则,数据库保存的索引是无序的)
2.5枚举最不好的地方在于字符串列表是固定的,添加或删除字符串必须使用ALTER TABLE,所以对于会改变的字符串,不要使用枚举。
3.char 和 varchar
3.1 char是定长,varchar是变长,也就是varchar节省空间(除非使用ROW——FORMAT=FIXED创建的话)
3.2 因为varchar是变长的,所以UPDATE时如果长度变长,就会做额外的工作
3.3 下列情况使用varchar:字符串列的最大长度比平均长度大很多;列的更新很少(所以碎片不是问题);使用了像UTF8这样的字符集(每个字符都使用不同的字节数进行存储)
3.4 CHAR适用情况:很短,或者所有值都接近同一个长度(如MD5);列经常变更
3.5 末尾空格问题:高版本varchar会保留末尾空格;char和低版本varchar会剔除末尾空格。
3.6 CHAR(N),VARCHAR(N)中N表示字符数,而非字节数(中文字符在UTF8中占用3字节)
3.7 虽然VARCHAR(N)数据类型在磁盘中存的就是他所表示的字符串的大小,但是读取到内存中的时候内存是会给他分配N*k+1or2(N<=255,1;else 2;)(k根据字符集决定)
4. 尽可能吧所有列定义为NOT NULL
4.1索引NULL列要额外的空间
4.2进行比较和计算时会对null值进行处理,可能导致索引失效
5. 时间日期数据类型
5.1 不要用字符串存储日期型数据,浪费空间
5.2 DATE能保存从1001到9999年,精度为秒,他把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,使用8字节
5.3 TIMESTAMP保存了从1970年以来的秒数,和Unix时间戳相同,只能保存1970到2038,使用4字节
5.4 FROM_UNIXTIME()和UNIX_TIMESTAMP()两个函数转换日期和Unix时间戳
5.5 DATE和TIMESTAMP中存的是时间,但是是哪里的时间呢???:前者不管哪里,他就是一个时间表示(与时区无关),后者是格林尼治时间。。就是说存储时DATE就按照给的时间存,TIMESTAMP则是在先根据所在时区和给的时间戳算出对应的格林尼治时间再存,访问时DATE就按照他存的时间返回,TIMESTAMP则是根据存的时间戳(看作格林尼治时间)和所在时区算出所在时区的对应时间。
5.6 通常用TIMESTAMP,空间效率高
5.7 MYSQL没有提供比秒更小粒度的日期和时间值,如果需要,可以用BIGINT存储微妙级别的时间戳,或用DOUBLE存储秒之后的小数部分。
6.整数类型
6.1 TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,分别用8,16,24,32,64存
6.2 整数都有UNSIGNED可选属性
6.3 对于存储和计算来说INT(1)和INT(20)是相同的,INT(N)中N只是规定了一些交互工具来显示字符的个数
7.实数类型
1.金融类要用DECIMAL
2.DECIMAL可以保存BIGINT范围外的整数
3.FLOAT和DOUBLE使用标准的浮点运算进行近似计算
1.1 将ip用UNSIGNED INT存:内置函数INET_ATON(字符串)和INTE_NTOA(整数)分别是点分十进制字符串和整数的转换函数
1.2 非负数用无符号类型(比如前面ip值对应的数字一定为正,所以用的数据类型为无符号整形,ip是8为*4=32位,也就是而int也正好是32位,而ip对应的全是正的,如果是用有符号int存的话那就只能表示一半,所以要用无符号int)
1.3不要用TEXT,BLOB,或者把他们都分离到单独的扩展表中
2.使用枚举(ENUM)类型代替字符串
2.1枚举类型在内部实际存储为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的“查找表”
2.2可以通过SELECT 枚举类型的列+0 FROM 表名来隐式转换来看到具体的整数
2.3不要用数字作为ENUM枚举常量(如ENUM('1','2','3')),这种双重性容易导致混乱
2.4枚举字段是按照内部存储的整数而不是定义的字符串进行排序,但可以用FIELD()函数显式地指定排序顺序如:SELECT e FROM enum_test ORDER BY FIELD(e,'apple','dog','fish');(e是枚举字段),不过这会导致MySQL无法利用索引消除排序(什么叫索引消除排序呢:就是说在查询中对索引字段排序,那这时其实是不用在执行一遍排序算法的,因为B+树保存索引,而B+树中维护的信息可以很快得到索引的顺序,相当于索引本身就是以有序的状态存储的。但这里你把他的原来的排序规则打破了,也就是显式地指定了排序顺序,那也就是相对于你规定的排序规则,数据库保存的索引是无序的)
2.5枚举最不好的地方在于字符串列表是固定的,添加或删除字符串必须使用ALTER TABLE,所以对于会改变的字符串,不要使用枚举。
3.char 和 varchar
3.1 char是定长,varchar是变长,也就是varchar节省空间(除非使用ROW——FORMAT=FIXED创建的话)
3.2 因为varchar是变长的,所以UPDATE时如果长度变长,就会做额外的工作
3.3 下列情况使用varchar:字符串列的最大长度比平均长度大很多;列的更新很少(所以碎片不是问题);使用了像UTF8这样的字符集(每个字符都使用不同的字节数进行存储)
3.4 CHAR适用情况:很短,或者所有值都接近同一个长度(如MD5);列经常变更
3.5 末尾空格问题:高版本varchar会保留末尾空格;char和低版本varchar会剔除末尾空格。
3.6 CHAR(N),VARCHAR(N)中N表示字符数,而非字节数(中文字符在UTF8中占用3字节)
3.7 虽然VARCHAR(N)数据类型在磁盘中存的就是他所表示的字符串的大小,但是读取到内存中的时候内存是会给他分配N*k+1or2(N<=255,1;else 2;)(k根据字符集决定)
4. 尽可能吧所有列定义为NOT NULL
4.1索引NULL列要额外的空间
4.2进行比较和计算时会对null值进行处理,可能导致索引失效
5. 时间日期数据类型
5.1 不要用字符串存储日期型数据,浪费空间
5.2 DATE能保存从1001到9999年,精度为秒,他把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,使用8字节
5.3 TIMESTAMP保存了从1970年以来的秒数,和Unix时间戳相同,只能保存1970到2038,使用4字节
5.4 FROM_UNIXTIME()和UNIX_TIMESTAMP()两个函数转换日期和Unix时间戳
5.5 DATE和TIMESTAMP中存的是时间,但是是哪里的时间呢???:前者不管哪里,他就是一个时间表示(与时区无关),后者是格林尼治时间。。就是说存储时DATE就按照给的时间存,TIMESTAMP则是在先根据所在时区和给的时间戳算出对应的格林尼治时间再存,访问时DATE就按照他存的时间返回,TIMESTAMP则是根据存的时间戳(看作格林尼治时间)和所在时区算出所在时区的对应时间。
5.6 通常用TIMESTAMP,空间效率高
5.7 MYSQL没有提供比秒更小粒度的日期和时间值,如果需要,可以用BIGINT存储微妙级别的时间戳,或用DOUBLE存储秒之后的小数部分。
6.整数类型
6.1 TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,分别用8,16,24,32,64存
6.2 整数都有UNSIGNED可选属性
6.3 对于存储和计算来说INT(1)和INT(20)是相同的,INT(N)中N只是规定了一些交互工具来显示字符的个数
7.实数类型
1.金融类要用DECIMAL
2.DECIMAL可以保存BIGINT范围外的整数
3.FLOAT和DOUBLE使用标准的浮点运算进行近似计算