表的优化与列类型选择
列选取原则####
1、字段类型优先级
整型 > date,time > char,varchar > blob
因为 整型,time运算快,节省空间,char/varchar要考虑字符集的转换与排序时的校对集,速度慢,blob无法使用内存临时表
列的特点分析:
整型: 定长,没有国家/地区之分,没有字符集的差异
time: 定长,运算快,节省空间. 考虑时区,写sql时不方便 where > ‘2005-10-12’;
enum: 能起来约束值的目的, 内部用整型来存储,但与char联查时,内部要经历串与值的转化
char: 定长, 考虑字符集和(排序)校对集
varchar: 变长 要考虑字符集的转换与排序时的校对集,速度慢.
text/Blob:无法使用内存临时表
2、长度够用就行,不要慷慨(如smallint,varchar(N))
大的字段浪费内存,影响速度
以年龄为例 tinyint unsigned not null ,可以存储255岁,足够. 用int浪费了3个字节
以varchar(10) ,varchar(300)存储的内容相同, 但在表联查时,varchar(300)要花更多内存
3、尽量避免使用null
null不利于索引,要用特殊的字节来标注,在磁盘上占据的空间其实很大
实验:
建立两张字段相同的表,一个允许为null,一个不允许为null,录入相同的数据,使用explain查看索引文件的大小
create table t3(
-> name char(1) not null default '',
-> key(name)
-> )engine myisam charset utf8;
create table t4(
-> name char(1),
-> key(name)
-> )engine myisam charset utf8;
insert into t3 values('a'),('');
insert into t4 values('a'),(null);
explain select * from t3 where name='a';
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t3
type: ref
possible_keys: name
key: name
key_len: 3
ref: const
rows: 1
Extra: Using where; Using index
1 row in set (0.03 sec)
explain select * from t4 where name='a';
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t4
type: ref
possible_keys: name
key: name
key_len: 4
ref: const
rows: 1
Extra: Using where; Using index
1 row in set (0.00 sec)
比较两张表的key_len,可以发现允许null值的t4表的key_len要长于t3表,这是因为使用null之后,表要多储存一个字节,用来区分是否是null,另外null所占用的空间较大。
**还有一点就是,null不便于查询,where 列名 = null 和 where 列名 != null 都查询不到值,需要使用 where 列名 is null 或者 where 列名 is not null
enum列的说明
1、enum列在内部是用整型来存储的
2、enum列与enum列相关联速度最快
3、enum列比(var)char的弱势--在碰到与char关联时,要转换,花费时间
4、优势在于,当char非常长时,enum依然是整型固定长度,当查询的数据量越大时,enum的优势越明显
5、enum与char/varchar关联,因为要转换,速度要比enum->enum,char->char要慢,但有时也可以这样用--就是在数据量特别大的时候,可以节省IO
create table t5(
-> gender enum('male','female') not null default 'male'
-> )engine myisam charset utf8;
insert into t5 values('male'),('female');
+--------+
| gender |
+--------+
| male |
| female |
+--------+
select gender+0 from t5
+----------+
| gender+0 |
+----------+
| 1 |
| 2 |
+----------+