Mysql 选择优化的数据类型

Mysql支持的数据类型特别的多,选择正确的数据类型对于获得高性能至关重要。不要管存储那种数据结构,下买几个原则有助于做出更好的选择
更小的通常更好用
一般情况下,应该尽量选择使用可以正确的存储数据的最小的类型,更小的的数据类型通常更快,因为他们占用的更小的磁盘,内存和cpu缓存,并且处理时需要的cpu周期也更小
简单就好
简单的数据类型的操作通常需要更小的cpu周期,例如,整数比字符型操作代价更低,因为字符集和校验规则使用字符比较比整数更复杂。这里有两个例子,一个是应该是用Mysql内建的类型(date,time,datetime)而不是字符串来存储日期和时间,另外一个是应该整存储IP地址。
尽量避免NULL
很多表都包含可为空NUll的列,即使应用程序并不需要null也是如此,真是因为NUll 是列的默认属性,通常情况下最好指定not null。除非真的需要储存NUll。

在作为列的选择时,第一步需要确定合适的大类型:数字,字符串,时间
下一步选择具体的类型MySQL的数据类型可以存储相同的类型的数据,只是存储的长度和范围不一样,允许有精度,或者存储的物理空间不同。相同的大类型的不同的子类型数据有时候也有一些特殊的行为和属性。

1.1.1 整数类型

有两种类型的数字:整数和实数。如果存储整数。可以使用以下几种整数类型,TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT。分别使用8,16,24,32,64位存储空间。他们可以存储的范围从-2^(N-1)到2^(N-1),其中N是存储空空间的位数。
整数的类型有可以选择UNSIGNED属性,表示不允许有负值,这大致可以是整数的上线提高一倍。假如TINYINT UNSIGNED可以存储的范围是0~255,而TINYINT的存储的范围是-128~127。有符号和无符号类型使用的相同的存储空间,并具有相同的性能。因此可以根据实际情况选择合适的类型。
Mysql 可以为整数制定宽度,例如INT(11),对于大多数这个是没有意义的:他不会限制值的合法范围,只是规定Mysql的交互工具(Mysql 命令行客户端)用来显示这个字符的个数。对于存储计算来说,INT(1)和INT(8)是相同的。

1.1 .2 实数类型

实数是带小数的数字,然后他们并不是为了存储小数部分,也可以使用DECIMAL存储比BIGINT还要大整数。MySQL
既支持精确类型,也支持不精确类型。Float 和double类型支持使用标准的浮点运算进行近似计算。如果需要知道浮点运算是怎么计算的,则需要研究使用的平台的浮点数的具体实现。
浮点类型存储同样的值的范围的时候,通常比DECIMAL 使用更小的空间。FLOAT使用4个字节存储,DOUBLE占八个字节,但是存储数据量比较大的时候,可以考虑使用BIGINT代替DECIMAL,将需要的存储货币根据小数位的位数乘以相应的倍数即可。假如要存储财务数据的精确到万分之一,则把所有的金额乘以一百万存储在BIGINT中,这样可以避免浮点存储计算不精确的DECIMAL精确计算代价高的问题。

1.1.3 字符串类型

Mysql 支持多种字符串类型。每种类型还有很多变种。
VARCHAR和CHAR类型
varchar和char 类型是两种最主要的字符串类型。不幸的是,很难精确的描述这些值是怎么存贮在磁盘和内存中。因为这个更存储引擎有关。下面是两种类型的比较
VARCHAR
varchar类型用于存储可变长的字符串,是最常见的字符串类型,他比定长的类型更节省空间,因为他仅适用必要的空间(例如:越短的字符串适用越少的空间)
varchar需要适用1个或者1个额外字节记录字符串的长度:如果列的最大长度小于255或者等于255字节,则只是用一个字节表示。否则是两个字节。varchar节省了存储空间,所以对性能也有帮助,但是由于行是变长的,在update时可能使行变成比原来的更长,这样就需要额外的工作。
下面这些情况使用varchar是合适的:字符串列的最大长度比平均长度大得多;列更新的少,所以碎片不是问题;
使用了UTF-8 这样的复杂的字符集,每个字符都是使用不同的字节进行存储。
CHAR
char类型是定长的:Mysql总是根据定义的字符串的长度分配的足够的空间。当存储char时,Mysql会删除所有的空尾空格。char值会更具需要采用空格进行填充以便比较。
char 适合存储很短的字符串,或者都接近一个长度,例如,char非常适合存储密码MD5值,因为这是一个定长的值,对于经常变更的数据,char也比varchar 更好。因为定长的char更不容易产生碎片,对于非常段的列,char比varchar存储空间也也更有效率。例如char(1),来存储只有Y和N的值。如果采用单字节符集只需要一个字节,但是varchar(1),却需要两个字节,因为还需要记录长度的额外字节。
下面有一个具体的例子来说明。
首先新建一张只有一个char(10)字段的表,并且往里面插入一些值:
当检索这些值的时候,会发现string3末尾的空格被截断了。

mysql> create table char_test(char_col char(10));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into char_test(char_col) values('string1'),('  string2'),('string  ');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
mysql> select concat("*",char_col,"*") from char_test;
+--------------------------+
| concat("*",char_col,"*") |
+--------------------------+
| *string1*                |
| *  string2*              |
| *string*                 |
+--------------------------+
3 rows in set (0.00 sec)

如果用varhchar(10) 存储相同的值你会发现string3 后面的空格还在,如下

mysql> create table varchar_test(varchar_col varchar(10));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into varchar_test(varchar_col) values('string1'),('  string2'),('string  ');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
mysql> select concat("*",varchar_col,"*") from varchar_test;
+-----------------------------+
| concat("*",varchar_col,"*") |
+-----------------------------+
| *string1*                   |
| *  string2*                 |
| *string  *                  |
+-----------------------------+
3 rows in set (0.00 sec)

与char和varchar类似的类型还有binary和varbinary,他们是存储的是二进制的字符串。二进制字符串跟常规的字符串非常相似。但是二进制字符串存储的是字节码而不是字符。
BLOB和TEXT类型
BLOB和TEXT都是为了存储很大的数据而设计存储的字符串类型。分别采用二进制和字符串方式存储。
实际上,他们分别属于两组不同的数据类型的家族:字符类型的TINYTEXT,SMALLTEXT,TEXT,DENIUMTEXT,LONGTEXT;对应的二进制类型是TINYBLOB,SMALLBLOB,BLOB,DEMIUNBLOB,LONGBLOB。BLOB是SMALLBLOB的同义词。TEXT是SMALLTEXT同义词。
与其他类型不同,MySQL把每个BLOB和TEXT值当做一个独立的对象处理。存储引擎在存储时通常会特殊处理。当BLOB和TEXT值太大的时候,InnoDB会使用专门的“外部”存储区来进行存储,此时每个值在行内都需要1~4 个字节存储指针,然在在外部存储区存储实际的值。
BLOB和TEXT家族之间仅有不同的是BLOB存储类型是二进制数据,没有排序的规则或者字符集而TEXT类型有字符集和排序的规则。
枚举类型代替字符串类型
有时候可以使用枚举代替常用的字符串类型。枚举可以吧一些不重复的字符串存储成一个定义的集合。MySQL在存储枚举非常紧凑。会根据列表值的数量压缩到一个或者两个字节中。MySQL在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字–字符串”映射关系表的“查询表”。下面有一个列子:

mysql> create table enum_test(e enum('fish','apple','dog') not null);
Query OK, 0 rows affected (0.03 sec)

mysql> insert into enmu_test(e) values('fish'),('dog'),('apple');
ERROR 1146 (42S02): Table 'test.enmu_test' doesn't exist
mysql> insert into enum_test(e) values('fish'),('dog'),('apple');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select e from enum_test;
+-------+
| e     |
+-------+
| fish  |
| dog   |
| apple |
+-------+
3 rows in set (0.00 sec)

mysql> select e+0 from enum_test;
+-----+
| e+0 |
+-----+
|   1 |
|   3 |
|   2 |
+-----+
3 rows in set (0.00 sec)

1.1.4日期和时间类型

MySQL可以使用许多类型来保存日期和时间值,例如YEAY和DATE。MYSQL能够存储的最小时间颗粒为秒。
大部分时间类型没有代替品,因此么有什么是最佳选择的问题。唯一的问题就是保存日期和时间需要做什么?MySQL提供两种相似的时间类型:DATETIME和TIMESTAMP。对于很多的应用程序他们都能工作,但是在某个场景一个比另一个工作的更好。

DATETIME

这个类型能保存的大的范围的值,从1001到9999年。精确度是秒,把他的日期和时间封装成YYYYMMDDHHMMSS的整数中,与时区无关。使用8个自己存储空间。

TIMESTAMP

就像他的名字一样,TIMESTAMP保存了从1970年1月1日午夜以来的秒数。他和UNIX时间相同,TIMESTAMP只使用了四个字节的存储空间。因此他的范围比DATETIME小的多,只能保存从1970年到2038年。
通常也应该尽量使用TIMESTAMP,因此它比DATETIME空间效率更高。

1.1.5位数据类型

MySQL有少数存储类型使用紧凑的位数存储数据。所有这些位类型,不管是底层存储格式还是处理方式如何,从技术上讲都是字符串类型。
BIT
使用BIT列在一个列中存储一个或者多个true/false值。bit(1)定义一个包含单个类的字段,BIT(2)存储2位。依次类推。BIT列的最多长度是64个字节。
SET
如果需要保存多个true/false 可以使用这些列合并到一个set数据类型。他在MySQL内部是一系列打包的位的集合来表示的。

Guess you like

Origin blog.csdn.net/u011462448/article/details/47954839