MySQL系列(二)--数据类型

如何选择优化的数据类型:

当一个列有多种数据类型可以选择,选择顺序:数字类型、日期/二进制类型、字符类型,相同级别的数据类型,优先选择占用空间小的类型

1、通常更小的更好

  相同级别的数据类型,选择占据空间更小的数据类型。更小的数据类型通常更快,因为占用更少的磁盘、内存和CPU缓存,处理时需要的

CPU周期也更少,但是要确保需要存储值的范围

2、简单更好

  一个列可以选择多种数据类型

  1、优先选择整形,整型比字符操作的代价更低

  2、其次是日期和二进制类型

  3、最后是字符类型

  4、使用MySQL内置的类型date、time、datetime而不是String存储时间和日期

  5、使用整型存储IP地址

3、尽量避免NULL

  1、定义表结构是没有指定列为NOT NULL,默认都是可以为NULL的,除非是真的需要存储NULL值,否则最好指定列为NOT NULL

  2、如果查询可为NULL的列,对MySQL来说更难优化,因为可为NUL的列使索引、索引统计和值比较都更复杂。可为NULL的列使用更多的存储空

间,在MySQL中也要特殊处理。

  3、但是InnoDB使用单独的位(bit)存储NULL值,所以对于稀疏数据(很多值为NULL,只有少数行的列有非NULL值)有更好的空间效率,但是不

适用于MyISAM

  所以,选择数据类型是,第一步需要确认合适的大类型:数字、字符串、时间等。

选择具体类型

  MySQL的数据类型可以存储相同类型的数据,只是存储的长度和范围不一样、允许的精度不同、物理空间不同

  例如:DATETIME和TIMESTAMP都可以存储时间和日期,但是后者只使用前者一半的存储空间,并且会根据时区变化,有自动更新能力。

整数类型:

存储范围:从-2^(N-1)到2^(N-1)-1,N为存储的位数

TINYINT -128 127
SMALLINT -32768 32767
MEDIUMINT -8388608 8388607
INT -2147483648 2147483647
BIGINT -9223372036854775808 9223372036854775807

  可选UNSIGNED属性,表示不允许负值,大概可以使正数的上限提高一倍,例如TINYINT UNSIGNED存储的范围是0~255,而TINYINT的存储范围

是-128~127

  然而整数计算一般使用64位的BIGINT,即使在32位的环境(一些聚合函数是例外)

宽度:

  宽度对大多数应用都是无意义的,只是显示字符的个数,对于存储和计算来说,INT(1)和 INT(20)是相同的,不要以为int(2)就是存储

两位,能节省空间。

  如果int(3),插入的数据为123456,显示还是123456。如果不足3位,左边补空格,也可以选择UNSIGNED ZEROFILL,左边补0。

浮点数/定点类型:

float和double都是浮点型,保存数据可以不指定精度,默认会按照实际的精度来显示。

decimal为定点型,如果不指定精度,默认为(10,0)。

 

(M,D),M为精度,D为标度。M表示该值的总共长度,D表示小数点后面的长度。

整数部分不能超过定义的位数,否则出现异常。小数部分可以,但是只保留指定位数,会进行四舍五入。

 

CPU不支持DECIMAL的直接计算,而是MySQL服务器本身实现了DECIMAL的高精度计算,相对而言,CPU支持原生浮点计算,所以浮点计算明显更快。

  MySQL5.0+将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。例如,DECIMAL(18,9)小数点两边各保存9个数字,一共使用9个字节

,小数点占用1个字节,最多65个数字

  浮点型相比DECIMAL存储同样范围的值时,使用更少的空间,所以只有对小数进行精确计算时才使用DECIMAL--例如存储财务数据。因为浮点型

很可能出现误差。但是数据量很大的时候可以使用BIGINT代替。

PS:浮点型是非精确的数据类型

时间类型:

DATETIME:

  以YYYY-MM-DD HH:MM:SS.[.fraction]格式存储时间,默认精确到秒,可以通过datetime(6)=YYYY-MM-DD HH:MM:SS.fraction来表示微妙,微妙

最大是6位

  与时区无关,占用8个字节的存储空间

TimeStamp:

  以YYYY-MM-DD HH:MM:SS.[.fraction]格式存储时间,从1970-01-01到2038-01-19

  与时区相关,占用4个字节,实际上以int类型存储

  在行被修改的时候可以自动修改timestamp列的值,一般是数据修改时间

  如果存在多个timestamp列,默认只会更新第一个timestamp列

测试:

DROP TABLE IF EXISTS temp;
CREATE TABLE temp (t1 datetime, t2 TIMESTAMP);
INSERT INTO temp VALUES(NOW(),NOW());
SELECT * FROM temp;
SET time_zone = '-10:00';
ALTER TABLE temp MODIFY t1 datetime(3), MODIFY t2 TIMESTAMP(3);

Date:

  占用的字节数比字符串、datetime、int要少,只需要3个字节

  可以利用日期时间函数进行计算

Time:

  只存储时间类型

日期类型使用注意事项:

  不要使用字符串存储时间类型,因为字符串类型比日期类型占用空间大,日期类型可以进行对比,而且有丰富的函数可以使用

  int类型不如timestamp类型

CURRENT_DATE() 返回当前日期值,不包括时间部分

NOW() 返回时间和日期值

varchar和char:

varchar存储特点:

  1、char会将字符串末尾的空格自动删除,首部的空格不会删除,varchar不会

  2、varchar(n),n是字符的长度,而不是字节的长度,例如存放"abcdefg",设置varchar(7)

  3、列的最大长度小于255只占用一个额外字节用于记录字符串长度,如果大于255,会占用2个额外字节

varchar长度选择:

  1、使用最小符合需求的长度

  2、不要后期才对varchar长度进行修改,在MySQL5.7之前,长度修改会导致锁表,5.7之后,字段长度在255以内,才不会锁表

varchar(5)和varchar(200)存储'hello'的空间开销是一样的,性能不同:

  更长的列会消耗更多的内存,因为MySQL通常会分配固定大小的内存块来保存内布置。尤其是使用内存临时表进行排序或操作时会特别糟糕。

还有利用磁盘临时表进行排序的时候。

varchar使用场景:

  1、列的最大长度比平均长度大很多,因为varchar长度是可变的

  2、列很少被更新,长度更新,会产生页分裂的情况,产生存储碎片

  3、使用多字符集存储字符串,例如utf8,中文3个字节,英文一个字节

char存储特点:

  1、char类型是定长的

  2、char类型的列会删除末尾的空格

  3、char类型的最大宽度255

CHAR使用场景:

  1、几乎定长的字符串,例如密码的md5值(定长)、身份证号码和手机号等

  2、短字符串,例如Boolean类型Y和N,char要1byte,而varchar要2byte,因为还有一个计算长度的额外字节

  3、经常更新的字符串列,因为不容易产生碎片

二进制字符串类型:

BLOB和TEXT类型:为存储更大的数据而设计,分别采用二进制和字符方式存储,但是尽量避免使用

  字符类型: TINYTEXT/SMALLTEXT/TEXT/MEDIUMTEXT/LONGTEXT

  二进制类型: TINYBLOB/SMALLBLOB/BLOB/MEDIUMBLOB/LONGBLOB

两种类型区别:

  BLOB类型存储的是二进制数据,没有排序规则(和其它类型的排序不同,通常对每一列的最前max_sort_length字节进行排序,可以根据需求进行

配置或者使用ORDER BY SUSTRING(column,length))和字符集,而TEXT类型有字符集和排序规则

 

posted @ 2019-05-13 11:03  Diamond-Shine  阅读(415)  评论(0编辑  收藏  举报