`
engineer
  • 浏览: 22208 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用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
未完,待续......

 

分享到:
评论

相关推荐

    C学习深入学习总结

    3.2 你是否经常使用const常量来代替宏? 6 3.3 下面四种情况,你知道是各表示什么意思吗? 6 3.4 你知道const常量如何初始化吗? 7 4 enum枚举 7 4.1 到底enum所定义出来的类型是一个什么样的类型呢? 7 4.2 作为一...

    c# program

    51. 表现给最终用户的字符串不要使用硬编码而要使用资源文件替换之。 52. 不要硬编码可能更改的基于配置的字符串,比如连接字符串。 53. 当需要构建长的字符串的时候,使用StringBuilder不要使用string 54. ...

    sourdough-planner

    采购计划员 去做 版本0.5-UI / UX 用户体验 行动优先 ...使用内联的字符串枚举作为类型参数? printText(s: string, alignment: "left" | "right" | "center") 使用const enum而不是enum 在switch(myEn

    drf-typed-views:使用类型注释在Dango REST Framework中验证反序列化请求参数

    的不仅仅是类型更先进的验证: min_value / max_value换号验证字符串格式: email , uuid和ipv4/6 ; 使用Python的本机Enum进行“选择”验证快速示例: from rest_typed_views import typed_api_view@ typed_api_...

    C 语言编程常见问题解答.chm

    12.5 对字符串进行操作的标准库函数有哪些? 12.6 对内存进行操作的标准库函数有哪些? 12.7 怎样判断一个字符是数字、字母或其它类别的符号? 12.8 什么是“局部环境(locale)”? 12.9 有没有办法从一个或多...

    C语言编程要点

    12.5. 对字符串进行操作的标准库函数有哪些? 173 12.6. 对内存进行操作的标准库函数有哪些? 176 12.7. 怎样判断一个字符是数字、字母或其它类别的符号? 178 12.8. 什么是“局部环境(locale)”? 179 12.9. 有没有办法...

    C语言FAQ 常见问题列表

    previous up contents next C 语言常见问题集 原著:Steve Summit 翻译:朱群英, 孙 云 修订版 0.9.4, 2005年6月23日... o 8.6 我有个函数, 本该返回一个字符串, 但当它返回调用者的时候, 返回串却是垃圾信息。 ...

    Google C++ 编码规范

    这样的注释要使用全大写的字符串TODO,后面括号(parentheses)里加上你的大名、邮件地址等,还可以加上冒号(colon):目的是可以根据统一的TODO格式进行查找: // TODO(kl@gmail.com): Use a "*" here for ...

    你必须知道的495个C语言问题

    1.1 我该如何决定使用哪种整数类型? 1.2 为什么不精确定义标准类型的大小? 1.3 因为C语言没有精确定义类型的大小,所以我一般都用typedef定义int16和int32。然后根据实际的机器环境把它们定义为int、short、...

    《你必须知道的495个C语言问题》

    书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并分别给出了解答,而且结合代码示例阐明要点。 《你必须知道的495个C语言问题》结构...

    c语言程序设计标准教程

    还应该说明的是枚举元素不是字符常量也不是字符串常量, 使用时不要加单、双引号。 main(){ enum body { a,b,c,d } month[31],j; int i; j=a; for(i=1;i;i++){ month[i]=j; j++; if (j>d) j=a; } for(i=1;i;i++){ ...

    C++ Primer中文版(第5版)李普曼 等著 pdf 1/3

     第3章 字符串、向量和数组 73  3.1 命名空间的using声明 74  3.2 标准库类型string 75  3.2.1 定义和初始化string对象 76  3.2.2 string对象上的操作 77  3.2.3 处理string对象中的字符 81  3.3 标准库类型...

    你必须知道的495个C语言问题(PDF)

    1.1 我如何决定使用那种整数类型? . . . . . . . . . . . . . . . . . . . 1 1.2 64 位机上的64 位类型是什么样的? . . . . . . . . . . . . . . . . 1 1.3 怎样定义和声明全局变量和函数最好? . . . . . . . . ....

    C++Primer(第5版 )中文版(美)李普曼等著.part2.rar

     第3章 字符串、向量和数组 73  3.1 命名空间的using声明 74  3.2 标准库类型string 75  3.2.1 定义和初始化string对象 76  3.2.2 string对象上的操作 77  3.2.3 处理string对象中的字符 81  3.3 标准库类型...

    【05-面向对象(下)】

    Character之外,还可以通过传入一个字符串参数来构建包装类对象。 •如果希望获得包装类对象中包装的基本类型变量,则可以使用包装类提供的XxxValue()实例方法。 自动装箱与自动拆箱 •JDk还提供...

    在一小时内学会 C#(txt版本)

    除字符串,所有基本和内建类型 ? 结构 ? 枚举类型 引用类型 引用类型在堆(heap)中分配内存且当其不再使用时,将自动进行垃圾清理。和 C++ 要求用户显示创建 delete 运算符不一样,它们使用新运算符创建,且...

    Qt Creator 的安装和hello world 程序+其他程序的编写--不是一般的好

    加入的这个函数的作用就是移除字符串开头和结尾的空白字符。 12.最后,如果输入错误了,重新回到登录对话框时,我们希望可以使用户名和 密码框清空并且光标自动跳转到用户名输入框,最终的登录按钮的单击事件的槽 ...

    亮剑.NET深入体验与实战精要2

    1.3.9 字符串常见操作 21 1.3.10 几个常用的数学函数 27 1.4 .NET的面向对象之门 27 1.4.1 继承——“子承父业” 28 1.4.2 委托——“任务书” 35 1.4.3 事件——“年终分红” 42 1.4.4 反射——“解剖” 49 1.5 ...

Global site tag (gtag.js) - Google Analytics