目录
良好的逻辑设计和物理设计是高性能的基石,应该根据系统将要执行的查询来设计schema。
选择优化的数据类型
选择数据类型的原则
- 更小的通常更好
尽量使用可以**正确存储**的**最小**数据类型。
- 简单就好
简单数据类型需要更少CPU周期。
- 尽量避免NULL
可为NULL的列使索引,存储等更复杂。
数据类型
分类 | 类型 | 存储大小(字节) | 范围 | 范围(无符号) |
整数 | tintyint | 1 | (-128,127) | (0,255) |
smallint | 2 | (-32 768,32 767) | (0,65 535) | |
mediumint | 3 | (-8 388 608,8 388 607) | (0,16 777 215) | |
int | 4 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | |
bigint | 8 | ... | ... | |
实数 | float | 4 | ... | ... |
double | 8 | ... | ... | |
decimal(m,n) | 不定 | ... | ... | |
日期和时间 | date | 3 | 1000-01-01/9999-12-31 | |
time | 3 | 838:59:59'/'838:59:59' | ||
year | 1 | 1901-2155 | ||
datetime | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | ||
timestamp | 4 | 1970-01-01 -- 2037 | ||
字符串 | char(m) | m | 0-255字节 | |
varchar(m) | / | 0-65535 字节 | ||
tinyblob,tinytext | 0-255字节 | |||
blob,text | 0-65 535字节 | |||
mediumblob | 2^24 - 1 字节 | |||
mediumtext | ||||
longblob,longtext | 2^32 -1 字节 | |||
位 | bit | n | 不同引擎不同。 innodb,[n/8] |
|
binary(n) | n | n个字节 | ||
varbinary(n) |
整数
整数类型有可选的UNSIGNED 属性,表示不允许负值。
整数类型的选择只决定了MYSQL怎么在内存和磁盘中保存数据,整数计算一般使用64位的bigint,即使32位环境也如此(一些聚合函数例外,使用decimal或double)。
实数
decimal支持精确计算,float和double 由于CPU支持,比decimal更快。decimal在MYSQL 5.0以上被保存在一个二进制中(每4个字节存9个数字)。decimal(18,9)使用9个字节,小数点一个字节,整数部分4个字节,小数部分4个字节。
浮点类型存储同样范围的值时,比decimal节省空间,MYSQL使用double作为浮点计算的类型。
字符串
存储引擎存储char或者varchar值的方式,在内存中和磁盘上可能是不一样。
VARCHAR,可变长,需要1或2个字节存储长度信息。
char存储时,会把末尾空格截断,内部存储时,添加空格,读取出来时,默认空格会发现不存在了。
binary填充时默认填充的是\0,而不是空格。
日期和时间
MYSQL能存储的最小时间粒度为秒。但是MYSQL也可以使用微秒级的粒度进行临时运算。
如果需要微秒计算,则可以用bigint存储时间戳,或者double存储秒之后的小数部分。
除了特殊要求,通常尽量使用timestamp,它比datetime空间效率更高。
选择标识符
为标识列选择合适的数据类型非常重要。不仅考虑存储,还要考虑怎么执行计算和比较。
一旦选择了类型,要确保所有的关联表中关联字段都使用相同类型。
整数类型是个合适的选择。
如果可能避免使用字符串类型作为标识列。
如果是UUID,应该移除‘-’,更好的做法是UNHEX转成16字节数字,存储在binary(16)中。
ORM等产生的SQL会导致很严重的性能问题。
schema设计中的陷阱
- 太多的列
- 太多关联
- 全能枚举
- 变相枚举
- 确实需要NULL,用其他不可用到的值代替,增加复杂度
范式和反范式
根据经验吧
缓存表和汇总表
数据冗余表,提高查询
物化视图
物化视图指事先计算存储在磁盘上的表,MYSQL并不原生支持,可以使用Flexviews。
计算器表
增加更多的slot,以减少并发的机会。
加快ALTER TABLE 操作的速度
Mysql的alter table操作的性能对大表示个问题,Mysql执行大部分修改表的结构操作的方法是用新的结构创建一个空表,从旧表查出数据插入到新表,然后删除旧表。
mysql5.1之后,支持“在线”操作,这些功能不需要在整个操作过程中锁表。最近innodb也支持通过排序来创建索引,这使得索引更快且有个紧凑的索引布局。
不是所有的alter table操作都会引起重建表结构。有2种方法可以改变或者删除一个列的默认值
ALTER TABLE MODIFY COLUMN 将导致表重建。
ALTER TABLE ALTER COLUMN 会直接修改.frm文件不涉及表数据,所以很快。
只修改.frm文件
不受官方支持
CHANGE
, MODIFY
, 和ALTER
区别
ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
CHANGE [COLUMN] old_col_name new_col_name column_definition
MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name]
-
CHANGE
:-
可重命名列和修改列的定义
-
Has more capability than
MODIFY
, but at the expense of convenience for some operations.CHANGE
requires naming the column twice if not renaming it. -
With
FIRST
orAFTER
, can reorder columns.
-
-
MODIFY
:-
Can change a column definition but not its name.
-
More convenient than
CHANGE
to change a column definition without renaming it. -
With
FIRST
orAFTER
, can reorder columns.
-
-
ALTER
: Used only to change a column default value.
更多关于alter table 性能问题参考: https://www.cnblogs.com/hllnj2008/p/5045752.html