[原创]高性能MySQL----数据类型优化

数据类型的选择的基本原则
  • 更小的通常更好。更小的数据类型通常更快,因为它们占用更少的磁盘、内存和 CPU 缓存,并且处理时需要的 CPU 周期更少
  • 简单就好。简单数据类型的操作通常需要更少的 CPU 周期
  • 尽量避免 NULL。为 NULL 的列使得索引、索引统计和值比较都更为复杂,使得对于 MySQL 来说更难优化
数字类型
整数(whole number)类型

TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT 分别使用8,16,24,32,64位存储空间。存储范围是 -2(N-1) 到 2(N-1)-1
整数类型有可选的 UNSIGNED 属性,表示不允许负值,这大致可以使整数的上限提升一倍。有符号和无符号使用相同的存储空间,并具有相同的性能。
MySQL 可以为整数类型指定宽度,例如 INT(11),对大多数应用这是没有意义的:它不会限制值的合法范围。这是规定了 MySQL 的一些交互工具用来显示字符的个数。对于存储和计算来说,INT(1) 和INT(20) 是相同的

实数(real number)类型

实数是带有小数部分的数字。DECIMAL、FLOAT(4字节)、DOUBLE(8字节)。其中DECIMAL支持精确计算,因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用 DECIMAL ,但在数据量大的时候,可以考虑使用 BIGINT 代替 DECIMAL ,只需要将小数放大相应的倍数即可。

字符串类型

    字符串长度定义的不是字节数,而是字符数。

VARCHAR

    因为一个字符在不同字符集对应的字节数不同,所以在不同字符集下,VARCHAR 类型能定义的长度是不一样的。
    在 latin1(单字节字符集)下

严格模式下用 latin1 字符集创建 VARCHAR 长度为 65535 数据库.png

非严格模式的话,可以创建表,但是会有一个警告,因为 MySQL 数据库自动将 VARCHAR 类型转换成了 TEXT 类型

经过测试发现,VARCHAR 类型的最大长度为 65532 。这是因为还有其他别的开销。


严格模式下用 latin1 字符集创建 VARCHAR 长度为 65532 数据库.png

    在 GBK 或 UTF-8 字符集下

严格模式下用 GBK 字符集创建 VARCHAR 长度为 65535 数据库.png

严格模式下用 GBK 字符集创建 VARCHAR 长度为 65532 数据库.png

严格模式下用 UTF8字符集创建 VARCHAR 长度为 65532 数据库.png

不同字符集下对 max 的提示是不同的。因此 VARCHAR(N) 中的 N 指的是字符的长度。而文档中说明 VARCHAR 类型最大支持 65535 ,单位是字节,而且是表中所有 VARCHAR 列的长度总和,如果 VARCHAR 列的长度总和超过这个长度,依然无法创建


图片.png

VARCHAR 类型用于存储可变长字符串,比定长类型更节省空间,因为它仅仅使用必要的空间。VARCHAR 需要使用 1 或 2 个额外字节记录字符串的长度:如果列的长度大于255,则需要1个字节,否则需要2个字节
对于 InnoDB 存储引擎,由于行是变长的。在 UPDATE 一个可变长字符串时,使得比原行变得更长,导致 InnoDB 存储引擎进行页分裂来使行可以放进页内
下面这些情况使用 VARCHAR 是合适的:字符串列的最大长度比平均长度大很多;列的更新很少;使用了像 UTF-8 这样复杂的字符集,每个字符都使用不同的字节数进行存储

CHAR

CHAR 类型是定长的,MySQL 总是根据定义的字符串长度分配足够的空间。当存储 CHAR 值时,MySQL 会删除所有的末尾空格。CHAR 适合存储很短的字符串或者所有值的接近同一个长度。

BLOB 和 TEXT 类型

BLOB 和 TEXT 都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符串方式存储。实际上,它们分别属于两组不同的数据类型家族:字符串类型是TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT;对应的二进制类型是TINYBLOB,SMALLBLOB,BLOB,MEDIUMBLOB,LONGBLOB。
MySQL 对 BLOB 和 TEXT 列进行排序与其他类型是不同的:它只对每个列的最前 max_sort_length 字节而不是整个字符串做排序。如果只需要排序前面一小部分字符,则可以减少 max_sort_length 的配置,或者使用 ORDER BY SUBSTRING(column,length)

使用枚举(ENUM)代替字符串类型

MySQL 在存储枚举时非常紧凑,会根据列表值的数量压缩到一个或者两个字节中。MySQL 在内部会将每个值在列表中位置保存为整数,并且在 .frm 文件中保存 "数字 - 字符串" 映射关系的查找表。使用如果数字作为枚举常量的话,这种双重性很容易造成混乱。还有就是枚举字段是按照内部存储的整数而不是定义的字符串进行排序的,第一种解决方式是:按照需要的顺序来定义枚举列。第二种解决方式是:在查询中使用 FIELD() 函数显式地指定排序顺序,但这会导致 MySQL 无法利用索引消除排序。

日期和时间类型

DATETIME 和 TIMESTAMP ,MySQL 能存储最小时间粒度为秒。但是 MySQL 能使用微秒级的粒度进行临时运算。

DATETIME

能保存从 1001 年 到 9999 年,精度为秒,与时间无关。使用 8 个字节的存储空间。

TIMESTAMP

TIMESTAMP 类型保存了从 1970 年 1 月 1 日午夜(格林尼治标准时间)以来的秒数。使用 4 个字节的存储空间,因此它的范围比 DATETIME 小得多,只能从 1970 年到 2038 年。
MySQL 提供了函数 FROM_UNIXTIME() 把 Unix 时间戳转为日期,并提供了 UNIX_TIMESTAMP() 函数把日期转换为 Unix 时间戳。
如果要存储比秒更小粒度的日期和时间值,可以使用 BIGINT 类型存储微秒级别的时间戳或者使用 DOUBLE 存储秒之后的小数部分。

位数据类型
BIT

MySQL 把 BIT 当作字符串类型,而不是数字类型。当检索 BIT(1) 值时,结果是一个包含二进制 0 或 1 值的字符串,而不是ASCII 码的 "0" 或 "1",然而,在数字上下文的场景中检索时,结果是将位字符串转化成数字。这是相对让人费解的,所以应该谨慎使用 BIT 类型

SET

如果想要保存很多 true/false 值,可以考虑合并这些列到一个 SET 数据类型,它在 MySQL 内部是以一系列打包的位的集合来表示的。这样就有效地利用了存储空间。它的主要缺点是改变列的定义的代价较高:需要ALTER TABLE,这对大表来说是非常昂贵的操作。(需要获取表的排它锁)

选择标识符

为标识列选择适合的数据类型非常重要。一般更有可能用标识列与其他值进行比较,或者通过标识列寻找其他列。标识列也可能在另外表中作为外键使用。所以为标识列选择数据类型时,应该选择跟关联表中对应列一样的类型

  • 整数类型
    整数通常是标识列最好的选择,因为他们很快并且使用 AUTO_INCREMENT
  • ENUM 和 SET 类型
    对于标识列来说,ENUM 和 SET 类型通常是一个糟糕的选择,尽管对某些只包含固定状态或者类型的静态"定义表"来说可能是没有问题的。ENUM 和 SET 列适合存储固定信息
  • 字符串类型
    如果可能,避免使用字符串类型作为标识符,因为它们很消耗空间,并且通常比数字类型慢
    对于完全随机的字符串也需要多加注意,例如 MD5()、SHA1() 或者 UUID() 产生的字符串。这些函数生成的新值会任意分布在很大的空间内,这会导致 INSERT 以及一些 SELECT 语句变得很慢。
    如果存储 UUID 值,则应该移除 "-" 符号;或者更好的做法是,用 UNDEX() 函数转换 UUID 值为 16 字节的数字,并且存储在一个 BINARY(16) 列中,检索时可以通过 HEX() 函数来格式化为 十六进制格式。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容