MySQL中定义数据字段的类型对你数据库的优化是非常重要的。
注: MySQL支持多种类型,大主要有数值类型、日期/时间类型和字符串类型。
1. 数值类型
1.1 整数类型
数值型数据类型主要用来存储数字,不同的数据类型提供不同的取值范围,可以存储的值的范围越大,其所需要的存储空间也会越大。整数类型的字段可以添加AUTO_INCREMENT自增约束条件。
需要注意的是,在设计数据库的时候,在实体类中long型的变量对应BIGINT,INT对应int类型的成员变量。
例:
CREATE TABLE tb_emp1
(id INT(11),
name VARCHAR(25),
deptId INT(11),
salary FLOAT);
id字段的数据类型为INT(11),“11”表示该数据类型指定的显示宽度,指定能显示的数值中数字的个数。
注意:显示宽度和数据类型的取值范围是无关的。显示宽度只是指明MySQL最大可能显示的数字个数,数值的位数小于指定宽度时会有空格填充。但是,如果插入了大于显示宽度的值,只要该值不超过取值范围,数值依然可以插入,而且在查询该列值的时候,将会显示完整的插入值,而不会进行显示宽度处理。例如下列语句创建表user:
CREATE TABLE user
(id INT(4),name VARCHAR(20));
插入数据:INSERT
INTO user VALUES(
19999,
'qing');
查询结果显示:
+-------+------+
| id | name |
+-------+------+
| 19999 | qing |
+-------+------+
INT默认显示4,但是插入19999依然正常显示。请牢记:INT(3)中的数字3仅仅限制显示而已。
注: int(m)里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,没有影响到显示的宽度。
注:mysql不建议使用外键,
注:int(1)能存多少数据,整数据型显示的是数据的宽度。
int(M) M显示的宽度和存储空间大小无关
zerofill 使用说明,例如int(5)表示当数值宽度小于 5 位的时候在数字前面加’0’填满宽度,如果不显示指定宽度则默认为 int(11),zerofill默认为int(10)。注:当使用zerofill 时,默认会自动加unsigned(无符号)属性,使用unsigned属性后,数值范围是原值的2倍,例如,有符号为-128~+127,无符号为0~256。
注:mysql不建议使用外键,
注:int(1)能存多少数据,整数据型显示的是数据的宽度。
int(M) M显示的宽度和存储空间大小无关
(1)连接测试数据库
(2)创建测试表T1
createtable t1 (id1 int,id2 int(5));
desct1;
+-------+---------+------+-----+---------+-------+
|Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
|id1 | int(11) | YES | | NULL | |
| id2 | int(5) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
(3)插入数据直接查询,未能看到两个字段的不同
insert into t1 values (1,1);
select * from t1;
(4)改变id1,id2两个字段为zerofill,id1为默认长度’10’,id2为长度为’5’
altertable t1 modify id1 int zerofill;
altertable t1 modify id2 int(5) zerofill;
desct1;
+-------+---------------------------+------+-----+---------+-------+
|Field | Type | Null | Key | Default | Extra |
+-------+---------------------------+------+-----+---------+-------+
|id1 | int(10) unsigned zerofill| YES | | NULL | |
|id2 | int(5) unsigned zerofill | YES | | NULL | |
+-------+---------------------------+------+-----+---------+-------+
(5)查询两列数据,数值前面用’0’被全位数
select* from t1;
+------------+-------+
|id1 | id2 |
+------------+-------+
| 0000000001 | 00001|
+------------+-------+
(6)插入超出给定范围的值,可以正常存入
insertinto t1 values (1,1234567);
select* from t1;
+------------+---------+
|id1 | id2 |
+------------+---------+
|0000000001 | 00001 |
|0000000001 | 1234567 |
+------------+---------+
1.1.1.1.2. 浮点数类型和定点数类型
浮点类型有2种:单精度(FLOAT)和双精度(DOUBLE)。
定点类型只有DECIMAL。
二者都可以用(M,D)来表示,其中M称为精度,表示总的位数,D称为标度,表示小数点后的位数。
Ø 浮点型
设一个字段定义为float(5,3),如果插入一个数123.45678,实际数据库里存的是123.457,但总个数还以实际为准,即6位。
注:存钱使用INT和BIGINT里(最小单位为分),如果在设计表时使用FLOAT和DOUBLE时存钱,由于CPU使用的是浮点运算,得到的结果是有问题。
EX:2.2+1.1用浮点数来表示(二进制来表示):
注:能不用浮点数就不用,使用整数来处理。
注:能不用浮点数就不用,使用整数来处理。
注:BIT在生产环境使用不多,生产中存二进制使用:varbinary(注:存在里面的数无法读明白)
注:若使用auto_increment 定义INT字段的话,则此字段必须是主键;
Ø 定点数
注:浮点型在数据库中存放的是近似值,定点类型在数据库中存放的是精确值。
DECIMAL类型不同于FLOAT和DOUBLE,DECIMAL类型实际上是以串存放的。
注:不论是定点类型还是浮点类型,如果用户指定的数据超出精度范围,则会进行四舍五入处理。
- 问:如果不指定精度,系统如何处理?
- 答:FLOAT和DOUBLE在不指定精度的时候,默认按照实际的精度(由计算机硬件和操作系统决定),DECIMAL默认为(10,0)。
注:定点数以字符串形式存储,对精度要求高时使用decimal较好;尽量避免对浮点数进行减法和比较运算。
浮点数和定点数的应用中,大家要记住以下几点:
n 浮点数存在误差问题;
n 对货币等对精度敏感的数据,应该用定点数表示或存储;
n 编程中,如果用到浮点数,要特别注意误差问题,并尽量避免做浮点数比较;
n 要注意浮点数中一些特殊值的处理。
注:AUTO_INCREMENT
在oracle中若想让某列数值自动增加1的话,需要配合trigger与sequences,
mysql中这个auto_increment就可以直接完成这样的任务,auto_increment值从1开始,每行增加1,如果插入NULL值到该列时,此时会插入一个比该列中当前最大值加1的值,在一张表中只能有一列auto_increment,所以想要使用auto_increment列时,应该定义该列为NOT NULL,并定义为primary key或unique键,下面用例子来说明如何使用:
(1)建立测试表ai1
create table ai1 (id int auto_increment notnull primary key,name char(10));
(2)插入一条空数据
insert into ai1 values ();
select* from ai1;
+----+------+
| id |name |
+----+------+
| 1 | NULL |
+----+------+
(3)插入一条跳跃id的新数据
insertinto ai1 values (4,'suzzy');
insertinto ai1 values (2,' sam ');
select * from ai1;
+----+-------+
| id |name |
+----+-------+
| 1 | NULL |
| 2 | sam |
| 4 | suzzy |
+----+-------+
(4)插入一条id为空的数据,此时查看id的变化,会按照我们之前定义的,用最大值加1
insert into ai1 values (null,'suzzy');
select * from ai1;
+----+-------+
| id |name |
+----+-------+
| 1 | NULL |
| 2 | sam |
| 4 | suzzy |
| 5 | suzzy |
+----+-------+
注:如果在一张表中加两列auto_increment列时,会报错:
mysql>create table ai1 (id int auto_increment not null primary key,id2 intauto_increment not null);
ERROR1075 (42000): Incorrect table definition; there can be onlyone auto column and it must be defined as a key
总结: auto_increment属性,大大的解决了很多生产环境当中,序列的问题,看似简单的小属性参数,却能看出来设计者的高明。
1.1.1.2. 日期与时间类型
这里只是简单说一下DATE和TIMESTAMP类型:
- 使用CURRENT_DATE或者NOW()插入当前系统日期。
- 应该注意的是,CURRENT_DATE只返回当前日期值,不包括时间部分;NOW()函数返回日期和时间,但是在保存到数据库时,只保留其日期部分。
TIMESTAMP类型显示宽度固定在19个字符,且其值的存储是以UTC(世界标准时间)格式保存的,存储时间时对当前时区进行转换,检索时再次进行转换。即查询时,当前时区不同,显示的时间值是不同的。
EX:加一个0转化为整数型
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2018-07-05 14:40:03 |
+---------------------+
mysql> select now()+0;
+----------------+
| now()+0 |
+----------------+
| 20180705144058 |
+----------------+
mysql> select (now()+0)/1000000;
+-------------------+
| (now()+0)/1000000 |
+-------------------+
| 20180705.1441 |
+-------------------+
记录U秒now(4)
mysql> select now(4);
+--------------------------+
| now(4) |
+--------------------------+
| 2018-07-05 14:43:13.5586 |
+--------------------------+
datetime与timestamp的区别:
1.DATETIME的日期范围是1001——9999年,TIMESTAMP的时间范围是1970——2038年。
2.DATETIME存储时间与时区无关,TIMESTAMP存储时间与时区有关,显示的值也依赖于时区。在mysql服务器,操作系统以及客户端连接都有时区的设置。
3.DATETIME使用8字节的存储空间,TIMESTAMP的存储空间为4字节。因此,TIMESTAMP比DATETIME的空间利用率更高。
4.DATETIME的默认值为null;TIMESTAMP的字段默认不为空(not null),默认值为当前时间(CURRENT_TIMESTAMP),如果不做特殊处理,并且update语句中没有指定该列的更新值,则默认更新为当前时间。
1.1.1.3. 文本字符串类型
字符串类型用来存储字符串数据,也可以用来存储其他数据,比如图片和音频的二进制数据等等。
文本字符串分为两类:
- 文本字符串
- 二进制字符串
MySQL中文本字符串数据类型
varchar与char有什么区别:
注:从这三个特点来说a. 支持最大长度b. 对格式的处理c. 变长的varchar的特点
Char最多可以支持255个字符,varchar支持65535个字符,
Char定长(对空格的处理),varchar变长,
区别一:定长和变长特点(char 表示定长,长度固定,varchar表示变长,即长度可变。)
说明: 如char(10),表示存储的是10个字符,无论你插入的是多少,都是10个,如果少于10个,则用空格填满。而varchar(10),小于10个的话,则插入多少个字符就存多少个。
区别二:对格式的处理(char需要处理空格。varchar是实际存储值)
区别三:支持长度不一样(Char最多可以支持255个字符,varchar支持65535个字符);
注:length:查看字节数、char_length:查看字符数
-- length():返回字符串所占的字节数(受编码影响)
-- char_length():返回字符串中的字符数
select length('中国'),char_length('中国'); -- 6、2
EX:varchar(10), char(10)
Create tablet1(c1 varchar(10),c2 char(10));
INSERT INTO t1 VALUES ('ab ', 'ab ');--AB后空两格
select char_length(c1),length(c1), char_length(c2),length(c2) from t1;
注:在char中没有空格
注:在varchar中没有删除空格处理
select concat('(', c1, ')'), concat('(',c2,')') from t1;
varchar分配低于255字节,需要一个1byte额外的开销;
varchar 大于255,要2个byte做额外开销;
【1】定长字符串char
磁盘(二维表)在定义结构的时候,就已经确定了最终数据的存储长度。
Char(L):L代表length,可以存储的长度,单位为字符,最大长度值可以为255。
char(4):在UTF8环境下,需要4*3=12个字节存储空间;GBK编码环境下需要4*2=8个字节存储空间(在java中使用两个字节来表示一个字符)。
Java基本类型占用的字节数:
1字节: byte , boolean
2字节: short , char
4字节: int , float
8字节: long , double
注:1字节(byte)=8位(bits)
①ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。
②UTF-8编码中,一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
③Unicode编码中,一个英文等于两个字节,一个中文(含繁体)等于两个字节。
文本符号:英文标点占一个字节,中文标点占两个字节。
④UTF-16编码中,一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。
⑤UTF-32编码中,世界上任何字符的存储都需要4个字节。
⑥GBK编码中,一个英文字符等于一个字节,一个中文(含繁体)等于两个字节。
注:GB2312 是对 ASCII 的中文扩展,而GBK 包括了 GB2312 的所有内容(GBK 比GBK2312 多出近20000个新的汉字,包括繁体字和符号)。
【2】变长字符串varchar
变长字符串在分配空间的时候按照最大长度的空间分配,实际用了多少根据具体的数据来定。
Varchar(L) : L表示字符长度,理论可以存储65536个字符。会多出1-2个字节来确定存储的实际长度。如果字符长度大于255,那么既不使用定长,也不使用变长,而是使用文本字符串text。
Varchar(10):储存10个汉字,UTF8下使用10*3+1=31个字节(大于255使用两个字节存储)。
以下占用字节,均表示在分配空间的时候所需要的字节(字符概念,一个字符使用三个字节存储-UTF8),如A占用字节为3,但是MySQL自身存储的时候会使用一个字节存储(会对英文字母和符号进行优化):
在生产环境中如何选择定长或者变长字符串类型呢?
定长的磁盘空间比较浪费,但是效率高:如果数据长度基本一样,就选择定长;如身份证,手机号码等。
变长的磁盘空间比较节省,但是效率低:如果数据不能确定长度(不同数据长度有变化),如姓名,地址等。
text与blob的区别在于:
text不能存储图片。
blob是二进制流,text是非二进制
mysql 的二进制数据类型 BINARY, VARBINARY,BLOB 都没有字符集的概念
再存取blob数据时,要入库时base64,出库时再base64
-----------------------------------------------------
1.blob是二进制大对象,可以容纳可变量数量的数据,其中blob分为4中类型:TINYBLOB,BLOB,mediumblob和LongBlob,他们容纳的长度是不同的.
Text同样也分为四种类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
2.blob被视为二进制字符串,Text被视为非二进制字符串;
blob列没有字符集,并且排序和比较基于列值字节的数值值。
TEXT列有一个字符集,并且根据字符集的校对规则对值进行排序和比较。
在TEXT或BLOB列的存储或检索过程中,不存在大小写转换,当未运行在严格模式时,如果你为BLOB或TEXT列分配一个超过该列类型的最大长度的值值,值被截取以保证适合。如果截掉的字符不是空格,将会产生一条警告。使用严格SQL模式,会产生错误,并且值将被拒绝而不是截取并给出警告.在大多数方面,可以将BLOB列视为能够足够大的VARBINARY列。同样,可以将TEXT列视为VARCHAR列。
3.BLOB和TEXT在以下几个方面不同于VARBINARY和VARCHAR.
BLOB和TEXT列不能有默认值.
当保存或检索BLOB和TEXT列的值时不删除尾部空格。(这与VARBINARY和VARCHAR列相同).
对于BLOB和TEXT列的索引,必须指定索引前缀的长度。对于CHAR和VARCHAR,前缀长度是可选的.
LONG和LONG VARCHAR对应MEDIUMTEXT数据类型。这是为了保证兼容性。如果TEXT列类型使用BINARY属性,将为列分配列字符集的二元校对规则.
MySQL连接程序/ODBC将BLOB值定义为LONGVARBINARY,将TEXT值定义为LONGVARCHAR。由于BLOB和TEXT值可能会非常长,使用它们时可能遇到一些约束.
BLOB或TEXT对象的最大大小由其类型确定,但在客户端和服务器之间实际可以传递的最大值由可用内存数量和通信缓存区大小确定。你可以通过更改max_allowed_packet变量的值更改消息缓存区的大小,但必须同时修改服务器和客户端程序。例如,可以使用 mysql和mysqldump来更改客户端的max_allowed_packet值.
----------------------------------------------------------
ZEROFILL属性(零值)适用于所有数值类数据列类型,作用是,如果数值的宽度小于定义的显示宽度,则在数值前填充0。
UNSIGNED属性不允许数据列出现负数。
AUTO_INCREMENT属性可生成独一无二的数字序列。只对整数类的数据列有效。
NULL和NOT NULL属性设置数据列是否可为空。
DEFAULT属性可为数据列指定默认值。
【3】文本字符串
如果数据量超过255个字符,通常会使用文本字符串。
文本字符串根据存储的数据格式进行分类:
Text:存储文字;
Blob:存储二进制数据,如图片、音频等。
通常二进制数据实际上数据库存储路径,物理文件放在磁盘上面。
【4】枚举:enum,事先将所有出现的结果都设计好,实际存储的数据必须是预先规定的数据的一个。
其作用如下:
① 规范数据格式,数据只能是规定的数据中的其中一个;
② 节省存储空间,枚举通常有一个别名-单选框;枚举实际存储的是数值而不是字符串本身。
create table my_enum(
gender enum('男','女','保密')
)charset utf8;
desc my_enum;
insert into my_enum VALUES('男'); --有效数据
insert into my_enum VALUES('人妖');--无效数据
ERROR 1265 (01000): Data truncated for column 'gender' atrow 1
insert into my_enum VALUES('男女');--无效数据
注:男女可以用ENUM
上面几种数据类型,我们着重说一下CHAR和VARCHAR,ENUM,SET
CHAR(M)为固定长度的字符串,定义时指定字符串列长,保存时右侧填充空格以达到指定长度。M表示列长度,M的范围是0-255个字符。检索时,尾部的空格将会被删除。如果存入了一个超过M长度的字符串,会导致该字符串被截断,只保留前M位。
VARCHAR(M)是长度可变的字符串,M表示最大列的长度。M的范围是0-65535。
例如,VARCHAR(50) 定义了一个最大长度为50的字符串,如果输入的字符串只有10个字符,那么只需要实际存储的是10个字符和一个长度信息字符。VARCHAR在值保存和值检索的时候,空格保存。
1.2. 数据类型的属性
1.3. Mysql类型转换
一、两种类型转换方式:
1.CAST (value as type );
2.CONVERT ( value , type );
3.CONVERT( expr USING transcoding_name);
4.CONCAT
5.if函数
6.SELECT conv('A09C012CA92A',16,10) 将16进制转换为10进制
CAST() and CONVERT(... USING ...) 是标准 SQL语法。而CONVERT()的非USING 格式是ofis ODBC语法。
带有USING的CONVERT() 被用来在不同的字符集之间转化数据。在 MySQL中, 自动译码名和相应的字符集名称相同。例如。这个语句将服务器的默认字符集中的字符串 'abc'转化为utf-8字符集中相应的字符串:
SELECT CONVERT('abc' USINGutf8); (不区分大小写,但是不识别utf-8)
当你想要在一个CREATE ... SELECT 语句中创建一个特殊类型的列,则cast函数会很有用:
CREATE TABLE new_table SELECTCAST('2017-04-12' AS DATE);
concat函数,常用于连接字符串。如sql查询条件的like查询,
AND c.name likeconcat(#{param.value},'%')。
将Int 转为varchar经常用 concat函数,比如concat(1,'9') 得到字符串 '19',但是可能会有隐式类型转化的问题。
IF函数 mysql中if是函数而不是命令 IF(expr1,expr2,expr3)
如果 expr1 为真(expr1 <> 0 以及 expr1 <> NULL),那么 IF() 返回 expr2,否则返回 expr3。
IF() 返回一个数字或字符串,这取决于它被使用的语境:
mysql> SELECTIF(1>2,2,3); -> 3
mysql> SELECTIF(1<2,'yes','no'); ->'yes'
mysql> SELECTIF(STRCMP('test','test1'),'no','yes'); -> 'no'
如果 expr2 或 expr3 明确地为 NULL,那么函数 IF() 的返回值类型为非 NULL 列的类型。(这在 MySQL 4.0.3 中新加入)。 expr1 是作为一个整数值被计算的,这就意味着,如果测试的是一个浮点型或字符串值,就必须进行比较操作:
mysql> SELECTIF(0.1,1,0); -> 0
mysql> SELECTIF(0.1<>0,1,0); -> 1
在上面第一种情况下,IF(0.1) 返回 0,是因为 0.1 被转换为一个整数值,返回 IF(0) 的测试结果。这可能不是你所期望的。在第二种情况下,比较测试原浮点数是否为一个非零值。比较的结果被作为整数使用。缺省的 IF() 返回值类型 (当结果存储在临时表中时,这是非常重要的) 在 MySQL 3.23 中按下列方式确定: 表达式 返回值
表达式(expr2)或表达式(expr3)返回值为字符串 字符串
表达式(expr2)或表达式(expr3)返回值为浮点型值 浮点型
表达式(expr2)或表达式(expr3)返回值为整型 整型
如果表达式(expr2)和表达式(expr3)均是字符串,同时两个字符串均是忽略字母大小写的,那么返回值也是忽略字母大小写的(从 MySQL 3.23.51 开始)。
可转换的类型:
①BINARY
BINARY str 是CAST(str ASBINARY)的缩略形式。
BINARY不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解为在字符串比较的时候区分大小写。
因为有的MySQL特别是4.*以前的对于中文检索会有不准确的问题,可以在检索的时候加上BINARY。
BINARY保存二进制字符串,它保存的是字节而不是字符,没有字符集限制。(例如:binary(8)可以保存8个字符,每个字符占1个字节,共占8个字节。)进行比较时是按字节进行比较,而不是按字符(char),按字节比较比字符简单快速。按字符比较不区分大小写,而binary区分大小写,结尾使用\0填充,而不是空格。
假如给定了随意长度N,则 BINARY[N] 使 cast使用该参数的不多于 N 个字节。同样的,CHAR[N]会使 cast 使用该参数的不多于N 个字符。
在一些语境中,假如你将一个编入索引的列派给BINARY, MySQL将不能有效使用这个索引。为执行一个区分大小写的比较,可使用CONVERT()函数将一个字符串值转化为一个不区分大小写的字符集。其结果为一个非二进制字符串,因此LIKE操作也不会区分大小写:
SELECT 'A' LIKE CONVERT( value USING latin1 ) FROM table1;
②CHAR
· char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。
如果需要存储的字符串的长度跟所有值的平均长度相差不大,适合用char,如MD5。对于经常改变值,char优于varchar,原因是固定长度的行不容易产生碎片。对于很短的列,char优于varchar,原因是varchar需要额外一个或两个字节存储字符串的长度。
· varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储
例外:Myisam(MySql默认)引擎中使用ROW_FORMAT=FIXED(静态表)时,每行使用相同的空间,造成浪费。
char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。
③DATE
将数字以秒计算为时间。将字符串作为参数时,单位为毫秒 以下是实验结果
SELECTfrom_unixtime(1765915176) -->2025-12-17 03:59:36
SELECTfrom_unixtime(1765915176.00001) -->2025-12-17 03:59:36.00001
SELECTfrom_unixtime('1765915176') -->2025-12-17 03:59:36.000000
SELECTfrom_unixtime('1765915176.00001') -->2025-12-17 03:59:36.000010
但是有最高值限制 2038-01-19 11:14:08.000000,(2147483648-0.0000001)
最低为0或者null时:1970-01-0108:00:00 默认的起始时间,数值都是自己用mysql计算出来的,不知道会不会有其他因素限制。
④TIME
随便试了一下 应该是最大的运行结果 并且对于小数部分不起作用
select convert('888992222.00001',time) -->838:59:59
select cast('888992233' as time) -->838:59:59
数值型的在运行时 分秒的位置需要<60,同样 小数部分没发现对结果有影响
⑤DATETIME
如果使用sql,MySql同时支持
select cast "2010-07-03 10:26:46" asdate
select cast "2010-07-03 10:26:46" asdatetime
在Hql中比较时间时,hibernate语句 不能使用第二个,因为hibernate不支持。
select convert('2017-05-12 22:22:22',datetime);
select cast('2017-05-12 22:22:22' as datetime);
都是必须把格式对应完整时才会生效,后面的时分秒如果不加,会自动设定为00:00:00
⑥DECIMAL
大量数据计算时可以保留精度。
⑦SIGNED
符号数整数,转为Integer时 Integer可以省略
select cast('456123.12345' as signedInteger)
⑧UNSIGNED
无符号数,先取整后计算。结果为负时会报错。
1.1.4. 合理的选择数据类型
1.1.4.1. 选择合理范围内最小的
选择最小的数据范围,因为这样可以大大减少磁盘空间及磁盘I/0读写开销,减少内存占用,减少CPU的占用率。
1.1.4.2. 选择相对简单的数据类型
数字类型相对字符串类型要简单的多,尤其是在比较运算时,所以我们应该选择最简单的数据类型,比如说在保存时间时,因为PHP可以良好的处理LINUX时间戳所以我们可以将日期存为int(10)要方便、合适、快速的多。
但是,工作中随着项目越做越多,业务逻辑的处理越来越难以后,我发现时间类型还是用时间类型本身的字段类型要好一些,因为mysql有着丰富的时间函数供我使用,方便我完成很多与时间相关的逻辑,比如月排行榜,周排行榜,当日热门,生日多少天等等逻辑
Ø 不要使用null
为什么这么说呢,因为MYSQL对NULL字段索引优化不佳,增加更多的计算难度,同时在保存与处理NULL类形时,也会做更多的工作,所以从效率上来说,不建议用过多的NULL。有些值他确实有可能没有值,怎么办呢?解决方法是数值弄用整数0,字符串用空来定义默认值即可。
Ø 字符串类型的使用
字符串数据类型是一个万能数据类型,可以储存数值、字符串、日期等。
保存数值类型最好不要用字符串数据类型,这样存储的空间显然是会更大,而且在排序时字符串的9是大于22的,其实如果进行运算时mysql会将字符串转换为数值类型,大大降低效果,而且这种转换是不会走原有的索引的。
如果明确数据在一个完整的集合中如男,女,那么可以使用set或enum数据类型,这种数据类型在运算及储存时以数值方式操作,所以效率要比字符串更好,同时空间占用更少。
Ø VARCHAR与CHAR
VARCHAR是可变长度字符串类型,那么即然长度是可变的就会使用1,2个字节来保存字符的长度,如果长度在255内使用1个字节来保存字符长度,否则使用2个字符来保存长度。由于varchar是根据储存的值来保存数据,所以可以大大节约磁盘空间。
如果数据经常被执行更新操作,由于VARCHAR是根据内容来进行储存的,所以mysql将做更多的工作来完成更新操作,如果新数据长度大于老数据长度一些存储引擎会进行拆分操作处理。同时varchar会完全保留内部所有数据,最典型的说明就是尾部的空格。
CHAR固定长度的字符串保存类型,CHAR会去掉尾部的空格。在数据长度相近时使用char类型比较合适,比如md5加密的密码用户名等。
如果数据经常进行更新修改操作,那么CHAR更好些,因为char长度固定,性能上要快。
Ø 数值类型的选择
数值数据类型要比字符串执行更快,区间小的数据类型占用空间更少,处理速度更快,如tinyint可比bigint要快的多
选择数据类型时要考虑内容长度,比如是保存毫米单位还是米而选择不同的数值类型
1.1.4.3. 整数
整数类型很多比如tinyint、int、smallint、bigint等,那么我们要根据自己需要存储的数据长度决定使用的类型,同时tinyint(10)与tinyint(100)在储存与计算上并无任何差别,区别只是显示层面上,但是我们也要选择适合合适的数据类型长度。可以通过指定zerofill属性查看显示时区别。
1.1.4.4. 浮点数与精度数值
浮点数float在储存空间及运行效率上要优于精度数值类型decimal,但float与double会有舍入错误而decimal则可以提供更加准确的小数级精确运算不会有错误产生计算更精确,适用于金融类型数据的存储。