高性能MySQL(二)——Schema与数据类型优化

    科技2022-07-10  157

    选择优化的数据类型

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

    2、简单就好 简单数据类型的操作通常需要更少的CPU周期。

    3、尽量避免NULL 很多表都包含可为NULL(空值)的列,即使应用程序并不需要保存NULL也是如此,这是因为可为NULL是列的默认属性。通常情况下最好指定列为NOT NULL,除非真的需要存储NULL值。 可为NULL的列使得索引、索引统计和值比较都更复杂。可为NULL的列会使用更多的存储空间,在MySQL里也需要特殊处理。

    InnoDB使用单独的位(bit)存储NULL值,使用对于稀疏数据有很好的空间效率。

    整数类型

    如果存储整数,可以使用这几种数据类型:TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT。分别使用8,16,24,32,64位存储空间。 整数类型有可选的UNSIGNED属性,表示不允许负值,这大致可以使正数的上限提高一倍。 有符号和无符号类型使用相同的存储空间,并具有相同的性能。 你的选择决定MySQL是怎么在内存和磁盘中保存数据的。然而,整数计算一般使用64位的BIGINT整数,即使在32位环境也是如此。 MySQL可以为整数类型指定宽度,例如INT(11),对大多数应用这样是没有意义的:它不会限制值的合法范围,只是规定了MySQL的一些交互工具用来显示字符的个数。对于存储和计算来说,INT(1)和INT(20)是相同的。

    实数类型

    DECIMAL类型用于存储精确的小数。 因为CPU不支持对DECIMAL的直接计算,MySQL服务器自身实现了DECIMAL的高精度计算。相对而言,CPU支持原生浮点计算,所以浮点运算明显更快。 浮点和DECIMAL类型都可以指定精度。对于DECIMAL列,可以指定小数点前后所允许的最大位数。这会影响列的空间消耗。

    浮点类型在存储同样范围的值时,通常比DECIMAL使用更少的空间。和整数类型一样,能选择的只是存储类型;MySQL使用DOUBLE作为内部浮点计算的类型。 因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用DECIMAL。

    字符串类型

    VARCHAR和CHAR是两种最主要的字符串类型。 BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。 有时候可以使用枚举列来代替常用的字符串类型。枚举列可以把一些不重复的字符串存储成一个预定义的集合。

    1、VARCHAR VARCHAR类型用于存储可变长字符串,是最常见的字符串数据类型。它比定长类型更节省空间,因为它仅使用必要的空间(例如,越短的字符串使用越少的空间)。

    VARCHAR需要使用1或2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则只使用1个字节表示,否则使用2个字节。

    VARCHAR节省了存储空间,所以对性能也有帮助。但是,由于行是变长的,在UPDATE时可能使行变得比原来更长,这就导致需要做额外的工作。

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

    2、CHAR CHAR类型是定长的:MySQL总是根据定义的字符串长度分配足够的空间。当存储CHAR值时,MySQL会删除所有的末尾空格。CHAR值会根据需要采用空格进行填充以方便比较。

    CHAR适合存储很短的字符串,或者所有值都接近同一个长度。对于经常变更的数据,CHAR也比VARCHAR更好,因为定长的CHAR类型不容易产生碎片。对于非常短的列,CHAR比VARCHAR在存储空间上也更有效率。

    与CHAR和VARCHAR类似的类型还有BINARY和VARBINARY,它们存储的是二进制字符串。二进制字符串跟常规字符串非常相似,但是二进制字符串存储的是字节码而不是字符。

    3、BLOB和TEXT类型 它们分别属于两组不同的数据类型家族:字符类型是TINYTEXT, SMALLTEXT, EX, MEDIUMTEXT, LONGTEXT; 对应的二进制类型是TIMYBLOB, SMALLBLOB, BLOB, MEDIUMBLOB, LONGBLOB。BLOB是SMALLBLOB的同义词,TEXT是SMALLTEXT的同义词。

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

    3、枚举最不好的地方是,字符串列表是固定的,添加或删除字符串必须使用ALTER TABLE。因此,对于一系列未来可能会改变的字符串,使用枚举不是一个好主意,除非能接受只在列表末尾添加元素。 由于MySQL把每个枚举值保存为整数,并且必须进行查找才能转换为字符串,使用枚举列有一些开销。

    日期和时间类型

    MySQL可以使用许多类型来保存日期和时间值,例如YEAR和DATE。 除了特殊行为之外,通常也应该尽量使用TIMESTAMP,因为它比DATETIME空间效率更高。

    选择标识符

    一般来说更有可能用标识符列与其他值进行比较(例如,在关联操作中),或者通过标识列寻找其他列。标识列也可能在另外的表中作为外键使用,所以为标识列选择数据类型时,应该选择跟关联表中的对应列一样的类型。

    范式和反范式

    范式的优点和缺点

    优点: (1)范式化的更新操作通常比反范式要快。 (2)当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据。 (3)范式化的表通常更小,可以更好地放在内存里,所以执行操作会更快。 (4)很少有多余的数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY语句。

    缺点:通常需要关联。

    混用范式化和反范式化

    最常见的反范式化数据的方法是复制或者缓存,在不同的表中存储相同的特定列。

    缓存表和汇总表

    有时提升性能最好的方法是在同一张表中保存衍生的冗余数据。

    加快ALTER TABLE操作的速度

    MySQL执行大部分修改表结构操作的方法是用新的结构创建一个空表,从旧表中查出所有数据插入新表,然后删除旧表。

    Processed: 0.113, SQL: 8