赞
踩
序
合理的表设计是SQL优化的基础,所以在做SQL优化之前先了解下建表的一些基本原则。
字段类型解析
VARCHAR(变长字符串)
CHAR(定长字符串)
注意:字符串长度定义的是字符数而不是字节数。就是说char(10)同样存储10个字符,10个汉字和10个英文字母占用的存储空间是不同的。所以理论上不管VARCHAR还是CHAR更新后都可能导致需要更大的存储空间而发生页分裂。
慷慨是不明智的:能用varchar(5)则不用varchar(200)存储5个字符,因为更长的列将耗费更大的内存,MySQL会分配固定大小的内存块来保存内补值,特别当使用临时表时。只分配需要的空间。
DATETIME
TIMESTAMP
DATE
注意:不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性
建表规约
数据类型越小越好
在满足需求的前提下,越小的类型占用空间越小,间接减少磁盘I/O次数。
通常来说,越小的类型运算速度越快。
如果不允许负值,请勾选非负。
数据类型越简单越好
越简单的类型,比较或运算速度越快。例如:整型优于字符串。
使用Decimal存储小数
在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。
如果存储的字符串长度几乎相等,使用char定长字符串类型
如果字符串字段过长,超过2000,则考虑使用text类型并且独立一张表来存储该字段,使用主键关联,以减少常用数据所占用的存储空间,这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理 IO 次数,也能大大提高内存中的缓存命中率,避免影响其他字段索引效率。
联合查询列选择
控制列的数量
MySQL的存储引擎API通过行缓冲格式在引擎层和服务器层之间拷贝数据,然后在服务器层将缓冲内容解码成各个列。从行缓冲中将编码过的列转换成行数据机构的操作代价非常高,转换的代价依赖于列的数量。所以当一个表的列很多,但是查询的时候可能只会用到少部分列时,这时转换的代价过高,会影响性能。
适当的冗余字段减少联表,提高查询效率是可行的,但要考虑以下几点
单表行数超过 1000 万或者单表容量超过 2GB考虑分库分表
所有字段不允许Allow Null,必须有默认值。
NULL在MySQL中是一个特殊的值,在某些场景下可能导致不可预期的结果,例如:
不建议使用外键,外键概念在应用层解决
不建议使用存储过程,存储过程不利于维护,难以调试和扩展,没有移植性
不建议使用MySQL分区表
注意字符集的选择,尽量选择相同的字符集编码,否则查询时可能出现意料之外的情况(例如联表查询时)。同时如果联表操作关联字段的字符集或者排序方式不同,会导致不能使用索引。字符集的继承规则 数据库服务器配置 >> 库 >> 表 >> 列,生效规则(就近原则) 列 > 表 > 库)
MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率。
适当的数据冗余
范式与反范式
优点:
优点:
在企业中很好能做到严格意义上的范式或者反范式,一般需要混合使用
案例:
附录
分类 | 类型 | 大小(字节) | 范围(有符号) | 范围(无符号) | 说明 |
---|---|---|---|---|---|
整型 | TINYINT | 1 | (-128,127) | (0,255) | |
SMALLINT | 2 | (-32768, 32767) | (0,63535) | ||
MEDIUMINT | 3 | (-8 388 608, 8 388 607) | (0, 16777215) | ||
INT | 4 | (-2147483648, 2147483647) | (0, 4294967295) | ||
BIGINT | 8 | (-9223372036854775808, 9223372036854775807) | (0,18446744073709551615) | ||
小数 | FLOAT | 4 | (-3.402 823 466 E+38, 1.175 494 351 E- 38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0, (1.175 494 351 E-38, 3.402 823 466 E+38) | 单精度浮点数 |
DOUBLE | 8 | (1.797 693 134 862 315 7 E+308, 2.225 073 858 507 201 4 E-308), 0, (2.225 073 858 507 201 4E-308,1.7976931348623157E+308) | 0, (2.225 073 858 507 201 4 E- 308, 1.797 693 134 862 315 7 E+308) | 双精度浮点数 | |
DECIMAL | DECIMAL(M,D) ,如果M>D,为 M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | DECIMAL最适合保存准确度要求高,而且用于计算的数据 | |
日期时间类型 | DATE | 3 | 1000-01-01 到 9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59' 到 '838:59:59' | HH:MM:SS | 时间值或持续时间 | |
YEAR | 1 | 1901 到 2155 | YYYY | 年份值 | |
DATETIME | 8 | 1000-01-01 00:00:00 到 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值,与时间无关 | |
TIMESTAMP | 4 | 1970-01-01 00:00:00 到 2038-01-19 03:14:07 | YYMMDD hhmmss | 存储的是UTC时间戳,与时区有关 | |
字符串 | CHAR | 0-255 | 0-255 | 0-255 | 定长字符串,char(n)当插入的字符串实际长度不足n时, 插入空格进行补充保存。在进行检索时,尾部的空格会被去掉。 |
VARCHAR | 0-65535 | 0-65535 | 0-65535 | 变长字符串,varchar(n)中的n代表最大列长度,插入的 字符串实际长度不足n时不会补充空格。 | |
TINYTEXT | 0-255 | 0-255 | 0-255 | 短文本字符串 | |
TEXT | 0-65535 | 0-65535 | 0-65535 | 较长文本字符串 | |
MEDIUMTEXT | 0-16777215 | 0-16777215 | 0-16777215 | 长文本字符串 | |
LONGTEXT | 0-4294967295 | 0-4294967295 | 0-4294967295 | 极大文本字符串 | |
二进制字符串 | TINYBLOB | 0-255 | 0-255 | 0-255 | 不超过 255 个字符的二进制数据 |
BLOG | 0-65535 | 0-65535 | 0-65535 | 较长文本的二进制数据 | |
MEDIUMBLOG | 0-16777215 | 0-16777215 | 0-16777215 | 长文本的二进制数据 | |
LONGBLOG | 0-4294967295 | 0-4294967295 | 0-4294967295 | 极大的二进制数据 |
系列文章
上一篇:【MySQL优化(三)】性能监控分析 - Performance Schema
下一篇:【MySQL优化(五)】InnoDB索引结构及特点
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。