4.1选择优化的数据类型《schema与数据类型优化》

这一章关注的是MySQL 数据库的设计,与其他关系型数据库管理系统的区别。

1.的通常更(更快,占用更磁盘内存CPU 缓存,并且处理时需要的CPU 周期也更少)但是要确保没有低估需要存储的值的范围

2.简单就好,例如,型比字符操作代价,因为字符集和校对规则(排序规则)使字符比较比整型比较更复杂。MySQL 内建的类型date,time,datetime 而不是字符串来存储日期和时间,另外一个是应该用整型存储IP地址。

3.尽量避免NULL

更难优化,NULL 的列使得索引、索引统计和值比较复杂。占存储空间。NULL 的列被索引时,每个索引记录需要一个额外的字节。

也有例外,InnoDB 使用单独的位(bit)存储NULL 值,对于稀疏数据(少数不为空)有好的空间效率。不适用于MyISAM。

本章只讨论基本的数据类型。MySQL 为了兼容性支持很多别名,例如INTEGER、BOOL,以及NUMERIC。建表时采用数据类型的别名,用SHOW CREATE TABLE 检查,会发现MySQL 报告的是基本类型,而不是别名。

4.1.1 整数类型

存储整数:TINYINT(8),SMALLINT(16),MEDIUMINT(24),INT(32),BIGINT(64),范围从-2^(N-1) ~ 2^(N-1)-1,N 是存储空间的位数(8,16......)

可选的UNSIGNED (不允许负值,正数的上限提高一倍),例TINYINT UNSIGNED 存储的范围是0 ~ 255,TINYINT 是.128 ~127

有符号和无符号类型存储空间、性能相同。

整数计算:64 位的BIGINT 整数,即使在32 位环境也是如此。(聚合函数[对一组值执行计算,并返回单个值]例外,它们使用DECIMAL 或DOUBLE 进行计算)。

指定宽度,INT(11)对大多数应用这是没有意义的,存储和计算来说,INT(1) 和INT(20) 是相同。

4.1.2 实数类型

带有小数部分的数字。也可使用DECIMAL 存储比BIGINT 还大的整数。

DECIMAL存储精确的小数。DECIMAL 的直接计算CPU 不支持,MySQL服务器自带CPU 直接支持原生浮点计算,所以浮点运算更快

指定小数点前后所允许的最大位数,影响列的空间消耗。MySQL 5.0 将数字打包保存到一个二进制字符串中(每4 个字节存9 个数字)。DECIMAL(18,9) 12345678.87654321 ‘.’占1 个字节,前后4字节

DECIMAL 只是一种存储格式,计算中转换为DOUBLE 类型。

只在对小数进行精确计算使用DECIMAL。FLOAT 4 字节。DOUBLE 8 字节,相比FLOAT 有更高的精度和更大的范围。例如存储财务数据。但在数据量比较大的时候,可以考虑使用BIGINT 代替DECIMAL。

4.1.3 字符串类型

可自定义字符集排序规则,但会很大程度上影响性能

VARCHAR 和CHAR 类型:引擎存储CHAR 或者VARCHAR 值的方式在内存中和在磁盘上可能不一样

(1)VARCHAR

可变长字符串,ROW_FORMAT=FIXED 创建,定长存储,这会浪费空间

需要使用1 或2 个额外字节记录字符串长度:列的最大长度<=255 字节1 个字节,否则使用2 个字节。VARCHAR(1000) 2 个字节存储长度信息,1001字节的存储空间。

UPDATE 时可能使行变更长,导致额外的工作:行空间增长,页内没有更多空间可存储。MyISAM :将行拆成片段存储,InnoDB分裂页来放进页内。(没懂)

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

存储和检索时会保留末尾空格

InnoDB 把过长的VARCHAR 存储为BLOB

(2)CHAR

定长,根据字符串长度分配足够的空间删除末尾空格,存储很的字符串,接近同一个长度

例:密码MD5 值(定长的值)。

经常变更的值,CHAR 也比VARCHAR 更好,不易产生碎片

短的列,CHAR 更有效率。CHAR(1) 存储只有Y 和N 的值,只需要一个字节,VARCHAR(1) 两个字节,还有一个记录长度的额外字节。

填充和截取空格MySQL 服务器层处理的。

(3)BLOB 和TEXT 类型

存储很大的数据,二进制和字符方式存储。

TEXT 字符方式存储,类型是TINYTEXT,SMALLTEXT(BLOB的同义词),TEXT,MEDIUMTEXT,LONGTEXT 

BLOB :二进制存储,TINYBLOB,SMALLBLOB(TEXT 同义词),BLOB,MEDIUMBLOB,LONGBLOB。

当作独立的对象处理。值太大时,InnoDB 会使用专门的“外部”存储存储,行内1 ~ 4 个字节存储一个指针。

不同:BLOB没有排序规则字符集,TEXT 类型有。

排序:只对最前max_sort_length 字节不是整个字符串做排序。如只需要排序前面一小部分字符,则可以减小max_sort_length 的配置,或者ORDER BY SUSTRING(column, length)。

(4)磁盘临时表和文件排序

Memory 引擎不支持BLOB 和TEXT 类型,所以使用隐式临时表,如MyISAM 磁盘临时表,这样性能开销大

尽量避免使用BLOB 和TEXT 类型。如无法避免,使用SUBSTRING(column, length) 转换为字符串(在ORDER BY 子句中也适用),就可使用内存临时表了。但是要确保截取的子字符串足够短临时表的大小超过max_heap_table_size 或tmp_table_size内存临时表转换为MyISAM 磁盘临时表

例如,假设有一个1 000 万行的表,占用几个GB 的磁盘空间。其中有一个utf8字符集的VARCHAR(1000) 列。每个字符最多使用3 个字节,最坏情况下需要3 000字节的空间。如果在ORDER BY 中用到这个列,并且查询扫描整个表,为了排序就需要超过30GB的临时表。

(5)枚举代替字符串类型


这三行数据实际存储为整数,而不是字符串。可以通过在数字上下文环境检索看到这个双重属性:

缺点:与varchar关联慢得多

优点:

1.列都为enum类型时,关联变得很快:在“查找表”时采用整数主键而避免采用基于字符串的值进行关联;

2.enum列可以让的大小缩小

3.主键大小减小很多;(在InnoDB 表上,如表上有其他索引,减小主键大小会使非主键索引也变得更小。)

4.14日期和时间类型

例:YEAR和DATE,粒度为秒

DATETIME:1001 年到9999 ,精度为秒。YYYYMMDDHHMMSS 整数中,与时区无关。8 个字节

TIMESTAMP*(尽量使用)1970 年到2038 ,FROM_UNIXTIME() 函数把Unix 时间戳转换为日期,赖于时区。4个字节

4.15 位数据类型

bit(尽量避免使用)

定义:bit(8),tinyint同义词,值:b'00101100',一个字节表示1位,没有压缩存储

当做二进制对应的字符串类型,但在整数上下文会转换成数字

set

缺点:改变列代价高:需ALTER TABLE

以打包位的集合表示,有效利用存储空间

整数列进行按位操作:如tinyint

4.16选择标识符

1.标识列可作为外键使用

2.考虑存储类型,还需考虑怎么执行计算和比较,例如set和ENUM,做比较时转为字符串。

3.关联表中最好选用同样类型:混用会导致性能问题,隐式类型有错时难发现

(1) 整数类型最好且可使用AUTO_INCREMENT

(2) enum和set只适合独立表详情展示不适合关联查询

(3) 尽量避免字符串,因为很耗空间,且很慢:

(4)随机值,慎用

插入会写到索引不同位置,导致页分裂磁盘随机访问以及聚簇索引碎片

查询慢,因为逻辑行随机分布的,不如递增

如果存储UUID 值,则应该移除“-”符号;或UNHEX() 函数转换UUID 值为16 字节的数字,并且存储在BINARY(16) 列中。检索时可以通过HEX()函数来格式化为十六进制格式。

4.当心自动生成的schema

会导致严重性能问题。存储任何东西都会使用很大的VARCHAR 列比较的列使用不同的数据类型

对象关系映射(ORM)系统是另一种常见的性能噩梦。没优化。为每个对象的每个属性使用单独的行,甚至使用基于时间戳的版本控制,导致单个属性会有多个版本存在。

面向对象的方式工作,不需要考虑数据是怎么存储。“对开发者隐藏复杂性”的应用通常不能很好地扩展

4.1.7 特殊类型数据

IPv4 地址。经常使用VARCHAR(15) 存储,实际上是32 位无符号整数,不是字符串。用小数点为了阅读容易。应用无符号整数存储IP 地址。MySQL 提供INET_ATON()和INET_NTOA() 函数在这两种表示方法之间转换

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341