总结做为开发人员重点注意的内容!这是一篇有关高性能MYSQL第四章schema相关的笔记。java
在项目中,数据库表列有两个text字段,用来存储大文本,在数据规模达到40万后,若是查询没命中索引,发现耗时会达到5s以上,在表中删除这两个大字段后,就算全表扫描,耗时也不过0.6s左右。mysql
解决方案:sql
datetime 和 timestamp 比较数据库
相同点: 都能存储日期、时间,精确到秒。服务器
不一样点: timestamp 只占 datetime 一半存储空间,具有时区功能,同时容许的时间范围小得多。框架
类型及存储空间函数
int(11) 其中11只是指定显示宽带,对存储空间无任何影响。性能
能够指定类型为unsinged,但java不支持unsinged, 使用相同类型可能会有麻烦。操作系统
精确类型:decimal, 不精确类型: double, float。设计
decimal 支持存储和计算的精确。计算性能比浮点类型差一点。
decimal(11,4)表示支持4位精确小数,整数部分最多只能有7位数字。
decimal类型4个字节存储9个数字,decimal(18,9)占用9个字节,前面9位整数占4个字节,小数点1个字节,后面小数占4个字节。
mysql5.0版本及以上,decimal 最多存储65个数字。
浮点类型在表示一样范围,一般比decimal使用更少的空间。
在数据量比较大的状况下,能够用bigint代替decimal, 将小数的位数乘以相应的倍数转为bigint,可避免不精确的问题。
varchar 和char
varchar存储可变长的字符串,使用额外的1个或两个字节额外存储空间,表示字符串的长度。
varchar在table指定row_format=fixed状况下,也是定长的,这会致使空间的浪费。
varchar(256)使用一个字节存储字符字符数。varchar(1000)使用两个字节存储字符数。
update varchar字段可能会致使列变得更长,innodb存储引擎会致使出现分裂页的状况出现,myisam将行拆分红不一样的段存储。
varchar适用场景:最长字符串比平均字符串长度长不少。
char是定长的,不容易产生碎片,适用于存储密码或md5值, 或表示性别,F/M, varchar(1)须要两个字节,char(1)须要一个字节。
char 会截断末尾的空格。
varchar(5)和varchar(100)都能存储5个字符,但varchar(100)性能会比varchar(5)糟糕,因此最好选择合适的长度。
text与blob类型
text存储大文本,blob存储二进制数据。
大文本有关的类型: tinytext, smalltext, text, mediumtext, longtext。
二进制有关的类型: tinyblob, smallbolob, blob, mediumblob, longblob。
当text,blob太大时,会做为一个对象单独存储,行中使用指针指向数据位置。
我的建议少用或不用这种类型,或拆除到详情表,减小对查询带来影响
enum类型
字段定义:animal enum("dog", "fish", "cat")
enum 实际存储为整数,并在.frm文件中保存字符串-整数
对应关系。
看个列子更容易明白:
create table enum_test( id int auto_increment, animal enum("dog", "fish", "cat"), primary key(id) ); insert into enum_test(animal) values ("dog"), ("cat"), ("dog"), ("fish") ;
对该表进行查询:
select animal+0, animal from enum_test order by animal ;
能够看到排序是按照整数排序的,即定义的顺序进行排序,而不是字符串序。
解决方案:定义时按照字符串序定义。
自定义顺序排序使用field函数,但这样将没法使用索引:
select animal+0, animal from enum_test order by field(animal, "cat", "fish", "dog");
字段join效率比较: enum join enum > varchar join varchar > enum join varchar = varchar join enum。
使用alter talbe 在枚举类型中添加字符串时,会重建整个表,除非老是在末尾添加值。
坏处:当枚举值为数字时,很容易发生困惑,尽可能避免这种状况。
datetime类型:
timestamp:
不推荐本身使用整数值来存储时间,这和内部存储没什么差异,没带来什么好处却多了额外的处理逻辑。
书中推荐使用timestamp, 我的推荐使用datetime,timestamp花活太多。
bit类型
bit列能够存储多个true/false值,bit(17)能够存储17个true/false值,myisam 使用一个比特来存储一个单独的true/false值,innodb使用最小的整数值来存储bit列的值。
myisam: bit(17)使用17个比特存储。
innodb: tinyint 便可存储。
高性能mysql认为应该慎用这个类型,因此就不深究了。
set 类型
好处: 存储使用打包的位存储,占用空间少。
坏处: 没法经过索引查找,修改列定义代价较高:须要alter table。
权限控制使用例子:
create table acl_test( id int not null auto_increment, perms set('can_read', 'can_write', 'can_delete'), primary key(id) ); insert into acl_test(perms) values ('can_read,can_write'), ('can_read,can_delete') ; select * from acl_test where find_in_set('can_write', perms) ;
查询结果:
主键最好选择自增id为主键,对数据性能比较好,同时相对应orm也支持,可能存在某些orm层框架不支持联合主键的状况。
ip与int转换函数: inet_aton(), inet_ntoa()。