MySQL数据类型优化

自作多情 提交于 2020-03-17 05:50:25

1.更小的通常更好。

一般情况下,应该尽量使用可以正确存储数据的最小数据类型。更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期也更少。

2.简单就好。

简单数据类型的操作通常需要更少的CPU周期。例如:整型比字符操作代价更低,因为字符集和校对规则使字符比较比整型比较更复杂。这里有两个例子:一个是应该使用MySQL内建的类型而不是字符串来存储日期和时间,一个是应该用整型存储IP地址。

3.尽量避免NULL。

通常情况下最好指定列为NOT NULL,除非真的需要存储NULL值。如果查询中包含可为NULL的列,对MySQL来说更难优化,因为可为NULL的列使得索引、索引统计和值比较都更复杂。

通常把可为NULL的列改为NOT NULL带来的性能提升比较小,所以调优时,没有必要首先在现有schema中查找并修改掉这种情况,除非确定会导致问题。如果计划在列上建索引,就应该尽量避免设计成可为NUll的列。

 

时间和日期上,TIMESTAMP(4个字节)只使用DATETIME(8个字节)一半的存储空间,并且会根据时区变化,具有特殊的自动更新能力。另一方面,TIMESTAMP允许的时间范围要小很多,有时候它的特殊能力会成为障碍。

 

整数类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,分别使用8,16,24,32,64位存储空间。整数类型有可选的UNSIGNED属性,表示不允许负值,这大致可以使正数的上限提高一倍。例如TINYINT UNSIGNED可以存储的范围为是0~255,而TINYINT的存储范围是-128~127。

MySQL可以为整数类型指定宽度,例如INT(11),对大多数应用这是没有意义的。它不会限制值得合法范围,只是规定了MySQL的一些交互工具用来显示字符的个数。对于存储和计算来说,INT(1)和INT(20)是相同的。

 

DECIMAL类型用于存储精确的小数。在MySQL5.0和更高的版本,DECIMAL类型支持精确计算。对于DECIMAL列,可以指定小数点前后所允许的最大位数,这会影响列的空间消耗。MySQL5.0和更高的版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字).例如DECIMAL(18,9)小数点两边将各存储9个数字,一共使用9个字节:小数点前的数字用4个字节,小数点后的数字用4个字节,小数点本身占用一个字节。

浮点类型在存储同样范围的值时,通常比DECIMAL使用更少的空间。FLOAT使用4个字节,DOUBLE使用8个字节,相比FLOAT有更高的精度和更大的范围。

因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用DECIMAL——例如存储财务数据。

 

VARCHAR和CHAR是两种最主要的字符串类型。

VARCHAR类型用于存储可变长字符串,比定长类型更节省空间,因为它仅使用必要的空间。VARCHAR需要使用1或2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则使用一个字节表示,否则使用2个字节。

由于行是变长的,在UPDATE时可能使行变得比原来更长,这就导致需要做额外的工作。如果一个行占用的空间增长,并且在页内没有更多的空间可以存储,MyISAM会将行拆成不同的片段存储,InnoDB则需要分裂页来使行可以放进页内。

下面情况使用VARCHAR是合适的:字符串列的最大长度比平均长度大很多;列的更新很少,所以碎片不是问题;使用了像UTF-8这样复杂的字符集,每个字符都是用不同的字节数进行存储。

CHAR是定长的;MySQL总是根据定义的字符串长度分配足够的空间。当存储CHAR值时,MySQL会删除所有的末尾空格。CHAR适合存储很短的字符串,或者所有值都接近同一个长度。对于经常变更的数据,CHAR也比VARCHAR更好,因为定长的CHAR类型不容易产生碎片。

 

BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。

MySQL把每个BLOB和TEXT值当作一个独立的对象处理。当BLOB和TEXT值太大时,InnoDB会使用专门的外部存储区域来进行存储。此时每个值在行内需要1-4个字节存储一个指针,然后在外部存储区域存储实际的值。

 

有时候可以使用枚举列代替常用的字符串类型。枚举列可以把一些不重复的字符串存储成一个预定义的集合。MySQL在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字 - 字符串”映射关系的“查找表”。

CREATE TABLE enum_test(
    e ENUM('fish','apple','dog') NOT NULL
);

INSERT INTO enum_test(e) VALUES('fish','apple','dog');

这三行数据实际存储为整数,而不是字符串。如果使用数字作为枚举常量,这种双重性很容易导致混乱。枚举字段是按照内部存储的整数而不是定义的字符串进行排序的。

枚举最不好的地方是字符串列表是固定的,添加或删除字符串必须使用ALTER TABLE。

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!