您的位置:首页 > 数据库 > MySQL

【MySQL】MySQL数据模型、字符编码介绍与使用场景分析

2013-05-15 11:39 507 查看
下面分析的是针对MySQL中的MyISAM或者Innodb存储引擎进行分析的,对于其他几种引擎没有涉及。因为,不同引擎之间相同种类的数据类型,在底层的存储可能就会不同。

针对MyISAM于Innodb的简单介绍请看点击打开链接

在这里就不再继续赘述。这里只是针对MySQL中常使用到的数据类型在存储和使用上进行简单的分析。

MySQL中常用数据类型基本上存在数值类型,字符类型,时间类型;也包括其他不常用类型,比如enum,set,其实这两种类型也属于字符串类型中的一个子类。在这里我们分开进行分析。

数据类型

数值类型

类型介绍

针对数值类型,包括bigint,int,tinyint,可以分为有符号和无符号两种。注意当把一列设置为zerofill则数据库直接视为无符号整数(zerofill主要是使用0在数值的前面填充,一直填充到你设定的位数)。

比如:alter table table_name add column column_name int(10) zerofill。

它们主要的差别就是占据的位数不同,能表示的范围不同。其中这里需要注意的是当设定一个类型转换可能会添加位数比如上面sql中的int(10),其实它和int(1)在底层所占据的存储空间是一样子的,都是一个int类型的数值占据的字节数,而其中的位数只是为了在客户端显示。而当你设定位数而且设定zerofill之后,当你插入的数值位数不够你设定的位数的时候,会在前面填充0到达你的位数。所以,在有些场景下,能使用tinyint的不要使用int,不要以为设定了位数就可以节约了空间。

上面已经说到,对于数值类型可以设为无符号数,当设置为无符号数的时候,则只能表示正数,当插入负值就会报出异常错误。为了忽略错误继续执行其他的语句,则可以使用insert ignore into table_name values()语句。但是不建议,除非你能保证你插入的数据都是满足条件的,否则不要设置插入时忽略错误,因为数据库的保证是你应用程序的最后一道保证了。

字符类型

类型介绍

针对字符串类型,比较常用的就是char与varchar还有text。其中varchar是可变的,但是也是可以设定位数,存储需求取决于列值的实际长度。如果varchar声明的长度大于255,则会额外增加2个字节记录长度;如果是声明长度小于255字节,则仅使用1个字节记录长度。虽然存储的时候如果在配置中设定了ROW_FORMAT=FIXED,那么在实际存储中会按照你设置的位数去存储;否则按照实际的大小进行存储,但是还是建议varchar(num)中num设定按需设定,因为如果num过大,在加载进内存的时候,它会按照num进行分配内存。另外在实际存储中针对char,其会默认去掉末尾的空格,而varchar在5.x版本之后则不会。对于末尾空格是否消除可以通过设置来决定

使用场景

那什么时候使用char什么时候使用varchar那,当你的字符固定长度或者长度变化不大的时候选择char;当字符串比较短的时候建议使用char,因为,varchar需要额外一个字节保存长度;在字符串需要经常更新的时候也建议使用char,因为char是固定长度,它产生的碎片会少。

另外对于在varchar与char上建立索引还需要注意。对于varchar可以建立全文索引,索引的长度是你在创建列的时候设定位数的大小然后再加上1或者2个字节。比如varchar(100),那么在该列上建立索引的话,那么索引长度就是102字节。

特殊类型

现在说一下enum类型,这是个神奇的数据类型。我们创建一列为enum类型,alter table table_name add column type enum(‘first’, ‘second’),在数据库中存储它是按照值的次序去存储的,而且次序是从1开始的。比如上述例子first存储在第一个位置,second存储在第二个位置。这是非常有迷惑的。查询的时候你即可以使用”first“查询也可以使用数字查询select * from table_name where type = 1也可以select *
from table_name where type = ”first“。

因为你可以通过数字序号去查询,所以当你的enum类型中也是通过数字来表明的,那么在查询的时候就非常不易读。比如你有个列为:enum(‘0’,‘1’),当你想查询该列的值为0的记录,查询语句就为。select * from table_name where type = 1,就是查询type为该enum第一个值即0的记录。但是这个读起来让人以为是查询条件为1的所有记录。这是需要注意的地方。

有时候可以使用enum代替char或者varchar,因为enum的存储效率会更高。

字符编码

在mysql中字符编码主要有以下几个地方,服务器,数据库,表与列,链接还有客户端。可以通过查询数据库得到,而查看数据库所支持的编码方式可以通过show charset命令。数据库的编码具体截图如下:



其中对于编码设置规则如下:列定义缺失用表默认,表默认缺失用库默认,库默认缺失用服务器默认配置,而且支持混合设置。即在一个数据库中可以设置不同编码的表,甚至在一个表中也可以设置不同的编码格式的列(但是除非特殊使用场景,否则不建议如此,否则会导致表难以维护)。对于数据库中经常出现的乱码,那么就需要从服务器到客户端一层一层的筛选,看编码格式是否一致。

对于编码的修改可以通过配置文件进行修改,也可以在创建数据库的时候进行设置。

附录:

在这里科普一下和编码有关的内容。在当今经常使用到的编码(仅针对中文)主要分为一下几种。

GB 2312:是由我国标准化组织指定的,对于中文是双字节的编码规则,对于英文是采用单字长字符。

GBK:GBK的出现是因为当时Unicode规范颁布,中国颁布了自己的版本GB 13000。但是该版本没有具体的实现,微软公司为了继续拓展中国市场,就利用GB2312中没有使用的位数,然后包含GB13000所有的字符表示,开发出了GBK,后来在国内被大规模使用。

GB 18030:GBK虽然被广泛使用,但是它始终不是一个国标,而且中国定义的GB 13000标准一直没被开发,虽然GBK完全包含了GB 13000。后来由中国政府出面,制定并开发了GB 18030标准。该标准完全包括GBK全部字符,并扩展了字符。

三种标准都是两个字节来表示的而且向下兼容。同一个字符的编码在三个标准里是统一的。标准额外可以标识的字符是使用了其他标准中没使用的位数。对于使用GB2312不乱码的话,GBK肯定也不会乱码,但是反过来则不一定;同样GB18030和GBK也是如此。

unicode(统一码,万国码):它是一种编码规范,但是它不是一种实现,可以理解成定义了一种协议,但是具体实现就要看不同的组织。比如下面两种编码UTF-8、UTF-16.

UTF-8:是变长编码,由1到4个字节编码,但是在Java语言中可能存在6个字节编码的情况,xml和xhtmll的标准字符集。

UTF-16:是由2个字节编码,分为大端序和小端序两种编码方式,Java默认的编码规则。其中在win和linux下,是默认的小端序编码,mac下则是大端序。

其实还有UTF-32的,它是定长编码,采用连续的4个字节存储一个字符。

unicode(统一码,万国码):点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息