Mysql数据类型

1、整数和实数

INT用的最多,用32位存储空间,我们在创建整数类型时,可以指定宽度 INT(11),但它并没有限制数值的范围,只是规定了一些交互工具用来显示字符的个数。

对于INT(1)和INT(11),它们的存储和计算是完全相同的。

Decimal,Float,Double都能存储实数。只不过是Decimal有精确的精度,而Float,Double相反。如果想要存储对精度有严格要求的就必须得用Decimal,比如财务数据。但是Decimal的占用空间更大,Mysql是使用二进制字符串存储。每四个字节表示9个数字。而Float只需要4个字节,Double是8个字节。

其实一般情况下,我们都是存储分,用BigInt存储,这样就简单多了。

2、字符串类型

varchar是变长字符串,它不仅包含了字符集,还包括字符集的长度,一般用1个(小于255)或2个字节来表示,因为它不是定长的,所以比较节省空间。但如果更新较多,如果某一行过长的话,因为存储空间不够,容易产生碎片,这取决于不同的存储引擎。

char字符是定长的,可能要比varchar浪费空间,但不是绝对的。比如同样是存储1个字节的字符集,你用varchar就需要2个字节存储;char只需要1个字符,因为它没有表示长度的字节。

当我们在设计表的时候,如果所有行的字符长度都差不多的话,就可以考虑用char,相反如果最长的字符集长度要比平均字符串要长很多的话,就用varchar。

对于char类型,当要插入末尾带有空格的字符串,会自动截取掉。

对于varchar类型,当查询时会自动过滤掉空格,所以如果只想查询包含空格的字符串,不能字节使用“=somestring",而是可以用like或者Binary,或者根据长度来做。

这里用Binary之所以可以,是因为其用的是二进制存储。使用了Binary就是使用字节码去比较,而不是字字符串。另外,Binary(N)中的N是指的字节,这个也是和char和varchar不同的地方。

注意一般说字符串长度,指的都是字符,不是字节长度。对于utf8编码,10个字符最多可能要使用30个字节存储。

BLOB和TEXT一般都是分别为了存储大的二进制数据和大文本的。当其过大时,都会使用外部存储,在每个行内都需要1到4个字节的指针,表示实际存储地址。

3、日期类型

DATETIME

时间范围是从1001年到9999年,存储字节是8字节。他底层是采用YYYYMMDDHHMMSS格式的整数存储。

TIMESTAMP

时间和UNIX的时间戳相同,从1970年1月1日午夜到2038年,存储字节是4字节。通常情况下,我们最好使用TIMESTMAP。但其会受到时区的影响,相同值在不同的时区显示的值是不同的。

Mysql最小存储粒度是妙,如果想存储毫秒,可以直接使用Bigint类型存储。

在实际应用中,针对自己的实际要求选择合适的存储类型是很关键的,好的类型可以节省存储空间,提高使用性能。

除了基本数据类型,还是要注意数据表的设计,Mysql中包含有三个知名的范式。

第一范式就是每个列要保证原子性,意思就是不可再分。最典型的就是一个地址信息,存储的基础地址信息要分出省,市,地区,具体地址等字段,而不是只写到一列中。

第二范式是说一张数据表中不要描述多件事情,在第一范式的基础上,保证数据记录的唯一性,非主键字段只能完全依赖主键,不能部分依赖。

一个典型的例子就是学生课程学分的表。不合格的是,一个表中一行中存储学生姓名,课程名称,学分。标准的是一个表存储姓名,课程;一个表存储课程,学分。

第三范式意思是行中属性不可依赖其他非主属性,只能完全依赖主键。其实这个和第二范式还是有相似的地方,也是在满足第二范式的基础上的规定。比如一个表中有学号,姓名,年龄,学院,电话。电话是依赖于学院的。这就完全可以放在单独的一张表,存储学院和电话。那张表存储姓名年龄,学院。

至于第二范式和第三范式,其实是容易混淆的。我在网上找的解释,我觉得说的挺好的。

第二范式(2NF)和第三bai范式(3NF)的概念很du容易混淆,区分它们的zhi关键点在于,2NF:非主键列dao是否完全依赖于主键,还是依赖于主键的一部分;3NF:非主键列是直接依赖于主键,还是直接依赖于非主键列。

第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。考虑一个订单明细表OrderDetail其属性如下:               (OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。
因为我们知道在一个订单中可以订购多种产品,所以单单一个OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF的设计容易产生冗余数据。

可以把OrderDetail表拆分为:

OrderDetail(OrderID,ProductID,Discount,Quantity)

Product (ProductID,UnitPrice,ProductName)

来消除原订单表中UnitPrice,ProductName多次重复的情况。
第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。考虑一个订单表Order:      (OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID)。
其中OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity
等非主键列都完全依赖于主键(OrderID),所以符合 2NF。

不过问题是CustomerName,CustomerAddr,CustomerCity 直接依赖的是
CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。
通过拆分Order为Order(OrderID,OrderDate,CustomerID)和Customer(CustomerID,CustomerName,CustomerAddr,CustomerCity)从而达到 3NF。

参考资料:

1、高性能Mysql书籍;

2、 Mysql三大范式

--------EOF---------
微信分享/微信扫码阅读