MySQL类型介绍以及适用范围

来源:互联网 发布:胖子丁丁小吗 知乎 编辑:程序博客网 时间:2024/06/06 10:53

1. 整型类型

Tinyint(8位)
范围:无符号(0~256)、有符号(-128~127)
场景:一般用于存储数字字典,常量表的id,因为数据量十分有限,又是常量表,所以可以用它存储
Smallint(16位)
范围:无符号(0~65536)、有符号(-32768~32767)
场景:Tinyint的替代品,若常量表数据比较多,比如中国的省-市-自治区-区县-村镇,到这个范围下,基本够用了。中国有65536个村镇(区县)吗?
Mediumint(24位)
范围:无符号(0~16777216)、有符号(-8388608~8388607)
场景:1000w以内的数据,这个若是日志表,又是在一段时间内数据量可控,定时清理,Mediumint不失为是轻量级的int的一种id选择。
Int(32位):大多数场景,一般Java的int也支持不了这么长的整数位!
范围:无符号(0~4294967296)、有符号(-2147483648~2147483647)
场景:大多数的自增id场景,基本够用了。无符号40多亿数据,一般的中小型,互联网,基本够用。
Bigint(64位)范围:天文数字,在Java中必须特殊处理该数字类型——BigDecimal进行处理。
范围:无符号(0~18446744073709551616)、有符号(-922337203685478~922337203685477)。
场景:使用关系型数据库存储海量数据的id。千万大一位是亿,亿大一位是兆,兆在大一位是什么????不过数据量在这个范围,很难想象还用RDBMS进行管理。
有符号与无符号的最大区别就是是否支持负数。Unsigned一旦被选择上了,表示不允许负数,也就是存储无符号数。一般情况下无符号int类型的字段几乎可以满足系统要求了,就算是自增id类型。40多亿的mysql数据量也已经比较不小了。日交易量记录上千万比记录,一个月也就区区3亿记录。如果大于这个数量级的数据,又是实时数据,应该考虑分表分库。或者借助NoSQL,将数据量散列拆分开。扯远了,这里就是告诉大家,数值类型字段支持的范围。

2. 实数类型

其实基本上也就是指含有小数的数,也就是浮点类型的数据类型。
Float:4个字节存储
Double:8个字节存储
Decimal:允许65个数字
这里有位仁兄总结的浮点型和定点型计算的文章,很不错http://www.163ns.com/zixun/post/5226.html。
基本上float可以用作百分比,有点误差没关系,double精确度比float大。而Decimal是完全金额类型计算。有的非敏感的,金额不是特别精确的系统业务场景,笔者也见过也有人使用double的。(你说那些不精确的,被四舍的钱都哪去了,都归谁了?100个人也就算了,如果涉及到1000w个人,每个人被四舍了的几厘钱,甚至到分钱误差,加起来够买房子了吧?)

3. 字符串类型

字符串类型主要分为varchar、char与blob、text之间的PK了。
一定要将字符串类型的字段调优到极致,因为数据库中,我们面对最多的类型也就是字符串,而我们每天面对的最多的场景也就是对文字的处理。
varchar类型:用于存储可变长的字符串,比定长char类型节省空间(在通常情况下)。除非设置row_format=fixed,每一行是定长存储。varchar额外需要1~2个字节存储字符串的长度。当列的最大长度< span>字节,用1个字节存储长度。否则采取2个字节。而且在Mysql5以后,varchar字段不会将末尾的空格剔除了。
char类型:char是定长类型,那么在存取过程中,会根据字符串长度老老实实分配足够的空间。定长字符串类型不容易产生磁盘碎片,对于定长短列,char比varchar更有效。比如存储MD5或者SHA1值。
Blob类型:
存储二进制类型的大字段数据,没有排序规则以及字符集。
类型成员有:tinyblob;blob;mediumblob;longblob。
一般情况下存储图片、文档文件,用之。存储引擎在blob很大时借助外部存储(操作系统FS接口)进行特殊处理。
Text类型-对应于Oracle的clob:
存储字符方式存储大字段类型数据,有排序规则和字符集。
类型成员有:tinytext;text;mediumtext;longtext。
一般情况下存储文章,html页面内容。同理,在text很大时借助外部存储,进行特殊处理。
经验:
1)一般获取blob或者text记录的时候,将原始记录值进行截断——substring(字段名,大小)函数。之后再转换成为相应的字符串。这样可以使用到Mysql的内存临时表了,而避免了从磁盘上去取数据的IO。
2)临时表的大小超过配置的max_ heap_table_size(tmp_table_size)的时候内存临时表将使用磁盘临时表。(也就是说将内存密集型的case负载到了IO密集型)

4. 枚举类型

Mysql存取枚举,紧凑。一般代替常用的字符串类型。Mysql将枚举列表的个数将其压缩位1~2个字节存储。之后,再将每一个枚举值保存为一个整数数字,将整数数字与枚举字符串的值做键值对儿的映射。也就是说,实际上表中引用枚举的字段值存储的是数字。
实验证明,着实如此。
CREATE TABLE user2 (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
type enum(‘魏’,’蜀’,’吴’) CHARACTER SET utf8 DEFAULT ‘魏’,
PRIMARY KEY (id)
) ENGINE=InnoDB
执行查询的时候将type字段都加上一个数字,得出来的结果居然是数字,证明枚举底层使用的是数值类型进行的存取枚举。而且若是非要枚举做外键,那么基于基准测试给出的结果,枚举与枚举之间的外键关联QPS是最高的。Mysql内部对枚举的数值做了相应的排序优化。
场景:能够使用枚举做常量时,尽量不要用字符串类型。

5. 日期和时间

日期和时间类型有以下几种:date;time;year;timestamp;datetime;
date:相当于截取了datetime的date,范围时从公元0年1月1日,可以到公元9999年12月31日。
time:相当于截取了datetime的time,范围就是一天的24小时。
year:比较尴尬,临界值是69和70,输入69,基本上代表2069年。70就是代表1970年。范围值是0~99,分别代表,0~69:2000~2069;70~99:1970~1999。不是特殊情况,基本弃用。
最常用的应该是datetime与timestamp。
datetime:使用8个字节存储日期与时间,那么可以得出结论,date使用4个字节,time也是4个字节。精确到秒级别,与时区无关。范围是从1000年到9999年的日期和时间。
timestamp:使用4个字节存储日期与时间,不过范围只能表示从1970年~2038年。如果没有什么意外,看到这篇文章的同志们,大多数都能活到那一年,之后会不会出现timestamp2这种类型来扩大时间戳的范围,那就得看是不是有支持更大整型数值的类型出现了。在应用层使用long类型插入该字段的值,最后可以存储正确的日期时间,而且该字段依赖于时区。做国际化产品的时候需要特别注意!

6. SET类型

用于存储集合类型的集合类,集合元素里面基本上存储的是常量值,书中举了一个比较贴切的列子,就是权限控制的权限集合。其实也是代表一个人的聚合元素。但是呢,其实权限控制完全用整形也可以表示,就是类似于linux的权限数字,比如777代表该文件夹无任何限制可以被其他用户使用,访问,修改。
对于SET类型(mysql数据库中),在Java应用层获取该类型的值,使用字符串就可以,不过获取的值还需要另外处理,拆解字符串为字符串数组(使用,进行拆分)。

7. 特殊字段-ipv4地址的存取

存取ip地址可以使用mysql中的两个函数将ipv4字符串转换成为整数,整数的存取比字符串快。两个特殊的函数是:
Ip地址转成数字:select inet_aton(“192.168.1.1”);
结果
+————————–+
| inet_aton(“192.168.1.1”) |
+————————–+
| 3232235777 |
+————————–+
数字转换成为ip地址
select inet_ntoa(3232235778);
结果为:
+———————–+
| inet_ntoa(3232235778) |
+———————–+
| 192.168.1.2 |
+———————–+

0 0