使用ENUM来代替字符串类型

      有时你可以使用ENUM列来代替通常使用的字符串类型。一个ENUM列可以存储65,535个不同的字符串值。MySQL以紧凑的方式存储它们,通过列表中值的个数来决定把它们放到1个还是2个字节中。在MySql内部是用一个integer来存储每一个值,这个integer代表其在列表中的位置,在表的.frm文件中保持一个查询表(lookup table),这个查询表定义了number-to-string的对应关系。例如:

CREATE TABLE enum_test(e ENUM('fish','apple','dog') NOT NULL);
INSERT INTO enum_test(e) VALUES('fish'),('dog'),('apple');

      这3行实际存储为integers,而不是strings。you can see the dual nature of the values by retrieving them in a numeric context:

SELECT e+0 FROM enum_test;

e+0
1
3
2

       当你把ENUM的常量定义为数字的时候,ENUM的这种双重特性会使你感到十分困惑,例如ENUM('1','2','3')。我们建议你不要那样做。
在排序的时候会以其内部的integer的值来进行排序,而不是通过它们的字符串值,例如:

SELECT e FROM enum_test ORDER BY e;

e
fish
apple
dog

       你可以根据ENUM的这个特性来通过指定ENUM列表中各个元素的顺序使它们按照你自己的方式来进行排序。你也可以在你的查询语句中使用FIELD()来指定排序,但是这样就会阻止MySql使用索引来进行排序:

SELECT e FROM enum_test ORDER BY FIELD(e,'apple','dog','fish');

e
apple
dog
fish

      ENUM最大的不足是其列表中的字符串都是确定的,只能通过ALTER TABLE来增加或者删除字符串元素。因此,这不是个好主意当使用ENUM作为一个字符串类型而其中的列表元素在未来某个时候会发生变化的时候。MySQL在它自己的权限表中使用ENUM来存储Y和N。
       因为MySQL把每一个值存储为integer,所以它需要额外的开销来进行查找,并把integer转换为它们的字符串表示。This is usually offset by their smaller size,but not alwayes。连接CHAR(VARCHAR)列到ENUM列比CHAR(VARCHAR)连接到CHAR(VARCHAR)列要慢。为了说明这个,我们在我们应用程序中的一个表测试了它的性能:

CREATE TABLE webservicecalls (
day date NOT NULL,
account smallint NOT NULL,
service varchar(10) NOT NULL,
method varchar(50) NOT NULL,
calls int NOT NULL,
items int NOT NULL,
time float NOT NULL,
cost decimal(9,5) NOT NULL,
updated datetime,
PRIMARY KEY (day, account, service, method)
) ENGINE=InnoDB;


     这个表包含了110,000条记录,只有10MB大小,所以可以全部放到内存中。service列有5个不同的值,平均字符长度为4个字符,method列有71个值,平均长度为20个字符。
     我们复制了该表,把service和method列转换为ENUM,如下:

CREATE TABLE webservicecalls_enum (
... omitted ...
service ENUM(...values omitted...) NOT NULL,
method ENUM(...values omitted...) NOT NULL,
... omitted ...
) ENGINE=InnoDB;

     我们通过主键连接两个表,并测试了性能。如下是我们的查询语句:

mysql> SELECT SQL_NO_CACHE COUNT(*)
-> FROM webservicecalls
-> JOIN webservicecalls USING(day, account, service, method);

     我们使用不同的组合来连接VARCHAR和ENUM列,结果如下所示:

Speed of joining VARCHAR and ENUM columns
        Test Queries                       per second
VARCHAR joined to VARCHAR          2.6
VARCHAR joined to ENUM               1.7
ENUM joined to VARCHAR               1.8
ENUM joined to ENUM                     3.5
未完,待续......

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值