Hiperformance Mysql 3rd Edition
MySQL提供了大量不同的数据类型,选择合适的数据类型y有时是决定性能好坏的关键。如下是一些关于更好选择数据类型的建议:
1.越小的数据类型通常越好
一般来讲,尝试用最小的数据类型,可以正确的帮助你存储和代表你的数据。更小的数据类型,通常也会更快,因为它使用了更小的磁盘空间,CPU Cache。同时可以减少CPU的执行周期。
2.越简单越好。
简单的数据类型需要的CPU执行周期通常也会更少。比如,整数的比较开销比字符串的开销更少,因为字符串有字符集和相应的校对规则,导致字符串的比较也更加复杂。在很多数据库中通常用整数来储存IP地址,用MYSQL内建的日期类型来存储时间而不是用字符串。
3.如果可以不适用NULL,尽量不要使用NUll
在列的字段属性上,如果该字段本身不可能为NULL,尽量字段属性 NOT NULL,除非你打算在该字段上存储NULL值.
MYSQL在优化查询期间如果引用到可以为空的字段,优化会比较困难。因为可以为空的字段,导致索引的建立,索引统计信息的收集和字段值得比较都比较复杂。同时,一个可以为空的字段也会使用更多的存储空间,同时需要mysql内部执行特殊的处理。在innodb内部,每个可以为NULL的值,需要一个bit来表示,对于空间十分匮乏的数据库来说,能省则省。
如下分析一张目前OLTP的表:
mysql> show create table account\G;
*************************** 1. row ***************************
Table: account
Create Table: CREATE TABLE `account` (
`id` int(11) unsigned NOT NULL,
`account` char(32) NOT NULL,
`password` char(32) NOT NULL,
`gm` int(11) default '1000',
`thread` tinyint(4) NOT NULL default '0',
`time` int(11) NOT NULL default '0',
`last_logout` int(11) NOT NULL default '0',
`online_time` int(11) NOT NULL default '0',
`offline_time` int(11) NOT NULL default '0',
`ip` varchar(16) NOT NULL default '',
`lastplayerid` bigint(20) NOT NULL default '0',
`authed` int(11) unsigned NOT NULL default '1',
`idcardno` varchar(32) NOT NULL default '',
`goldpoint` bigint(20) NOT NULL default '0',
`bankcard` int(4) NOT NULL default '0',
`protectword` char(36) NOT NULL default '',
`end_protectedtime` int(11) unsigned NOT NULL default '0',
`err_num` int(11) unsigned NOT NULL default '0',
`err_time` int(11) unsigned NOT NULL default '0',
`hack_check_errcount` int(11) NOT NULL default '0',
`plugdata` blob,
`ppcardinfo` blob,
`pp_card_info` varchar(2048) default NULL,
`last_login_area` int(11) NOT NULL default '0',
`second_password` blob,
`login_check_details` blob,
`base` blob,
`msg_authed` int(4) NOT NULL default '1',
`safe_email_status` int(11) NOT NULL default '-1',
`safe_mobile_status` int(11) NOT NULL default '-1',
`vip_level` tinyint(4) default '0',
`vip_points` int(11) NOT NULL default '0',
`last_award_level` tinyint(4) default '0',
`last_award_time` int(11) default '0',
`vip_quest` tinyint(4) default '0',
`vip_time` int(11) NOT NULL default '0',
`qiangzhu` int(11) NOT NULL default '0',
`liquan` bigint(20) NOT NULL default '0',
PRIMARY KEY (`account`),
UNIQUE KEY `index_id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
对于这个表,其实可以看到很多明显的问题,最明显的就是primary key 使用字符串account字段,导致插入数据按照account排序,而不是用自增主键,会导致大量block分裂,导致碎片过多,影响dml效率。同时我们看到很多时候使用int(n)来限制一个整形的长度。其实对于int(n)的含义我想用 high performance mysql中的一段话来解释:
MySQL lets you specify a “width” for integer types, such as INT(11). This is meaningless
for most applications: it does not restrict the legal range of values, but simply specifies
the number of characters MySQL’s interactive tools (such as the command-line client)
will reserve for display purposes. For storage and computational purposes, INT(1) is
identical to INT(20).
其实对于int(n)其实对大多数应用来讲,根本没有多大意义。而且它也不能限制int的合法范围(-2147483648~2147483647),只是为了让MYSQL的交互工具显示的时候只显示N个字符而已。而且很多字段也可以加上NOT NULL属性,来提高性能。
同时保证每个字段都使用它最小的空间来存储。
尽量在设计表的前期就规划好字段的范围,并选择合适的类型,可能只是一点点小小的更改,有时候对整个系统来讲可能带来性能极大的提升。数据量存储空间越小,越能提升数据库的性能。
阅读(2689) | 评论(0) | 转发(1) |