MySQL表设计优化与索引 (八)
来源:Asp之家 发布时间:2010-10-25 19:46:00
使用ENUM代替字符串类型
有时候, 可以通过使用ENUM来代理常规的字符串类型。一个ENUM列能够存储65535个不同的字符串值,MySQL非常紧凑的存储这些值,会根据值列表把这些值存储到1到2个字节中。通过在表的.frm文件中保存一个数字到字符串的对应关系来保存一个”查询表”, 它把每个值存储成一个表示值在字段定义列表中的某个位置的整数。 下面是几个例子;
mysql> CREATE TABLE enum_test(
-> e ENUM(‘fish’, ‘apple’, ‘dog’) NOT NULL
-> );
mysql> INSERT INTO enum_test(e) VALUES(‘fish’), (‘dog’), (‘apple’);
这3列实际上存储的是整数, 而不是字符串。 能够通过在数字检索上下文中查看到这些值的两面属性:
mysql> SELECT e + 0 FROM enum_test;
+——-+
| e + 0 |
+——-+
| 1 |
| 3 |
| 2 |
+——-+
如果指定数字当做ENUM常量的话, 这个两面性太容易引起混淆了。建议不要这么做。
另外一个令人奇怪的是ENUM字段通过整数值来排序, 而不是字符串本省:
mysql> SELECT e FROM enum_test ORDER BY e;
+——-+
| e |
+——-+
| fish |
| apple |
| dog |
+——-+
通过指定期望的ENUM数字的排序顺序来解决这个问题。也可以通过在查询中显式的使用FIELD()来指定排序顺序, 但是这回使得MySQL在排序中无法使用索引:
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把每个值存储整数, 不得不在需要的时候做一些查询工作来转化成字符串表示,ENUM有一些开销的。这些有可能会通过他们相对较小的大小来缓冲, 但并不总是这样。特别是, 把CHAR或者VARCHAR列并成一个ENUM列比并成CHAR或者VARCHAR列要慢。
为了演示一下,我们对MySQL在一个应用中的一个表上做join做性能测试. 这个表有一个很宽的主键:
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条记录,大小只有10M, 所以能够全部放在内存中。service列包含有5个不同的值, 平均长度是4个字符, method列包含有71个值, 平均长度20个字符。
我们对这个表做了一个拷贝, 把service和method字段转化成ENUM类型,如下:
CREATE TABLE webservicecalls_enum (
… 省略 …
service ENUM(…values omitted…) NOT NULL,
method ENUM(…values omitted…) NOT NULL,
… 省略 …
) ENGINE=InnoDB;
然后测试联合两个表的主键列来测试性能,使用的查询如下:
mysql> SELECT SQL_NO_CACHE COUNT(*)
-> FROM webservicecalls
-> JOIN webservicecalls USING(day, account, service, method);
然后改变一下查询, 以不同的组合来联合VARCHAR和ENUM字段,表3-1中列出了结果。
表3-1. 联合VARCHAR和ENUM列的
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
把列转化成ENUM后, 联合速度变快了。但是联合ENUM和VARCHAR列慢一些。在这个例子中, 只要不需要与VARCHAR列进行联合,看起来转化成ENUM是一个不错的注意。
而且, 做类型转换有另外一个好处: 从SHOW TABLE STATUS结果着那个的Data_length列的值来看,把这两列换成ENUM后, 表只有原来大小的1/3了。 在某些情况下, 即使需要做与VARCHAR列的联合, 也是有好处的。 在转换后,主键的大小也只有原来的的一半。 因为这是一个InnoDB表, 如果还有其他索引的话,减少主键的大小可以使得索引大大减小。


猜你喜欢
- 简单介绍正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如
- 问题:在安装SP4补丁的时候,老是报验证密码错误。上网查了一下资料,发现是一个小bug。按照一下操作,安装正常。SQL Server补丁安装
- 本文实例讲述了Python实现的排列组合计算操作。分享给大家供大家参考,具体如下:1. 调用 scipy 计算排列组合的具体数值>&g
- 我们大家都知道CSS功能的强大,而有关CSS基本的排版控制虽然已有详细的使用说明和参考教程,但还有许多丰富的CSS排版能力,是很少能查到的。
- 本文实例讲述了python实现多进程按序号批量修改文件名的方法。分享给大家供大家参考,具体如下:说明文件名命名方式如图,是数字序号开头,但是
- 经常看到有人误删数据,或者误操作,特别是update和
- 以下的文章主要是介绍SQL Server数据库与其实际应用元数据,我前两天在相关网站看见SQL Server数据库与其实际应用元数据的资料,
- 这个是今年年初写的一篇,拿出来温习下。指针让程序结构变得混乱,也让程序执行效率提高,因此在oo的语言中不提倡指针的使用,使得程序结构清晰易读
- 简介对与控件QPushButton中的可以使用setStyleSheet设置它背景图片。具体设置背景图片的方法有两种self.button.
- 如下所示:select name from mysql.proc where db='数据库名';或者select rout
- 本程序将使用字典来构建有向无环图,然后遍历图将其转换为对应的Excel文件最终结果如下:代码:(py3) [root@7-o-1 py-da
- 说明:使用mysqldump –all-databases会导出所有库。但如果做主从,从主库dump出数据时,我们是不需要也不想要infor
- 一 简单介绍wxpy基于itchat,使用了 Web 微信的通讯协议,,通过大量接口优化提升了模块的易用性,并进行丰富的功能扩展。实现了微信
- 想通过编写Python代码来打开本地的.mp4格式文件,使用os模块来操作文件。我的电脑默认的是QQ影音播放器,执行Python代码打开默认
- 从MySQL 5.0.2开始,通过mysql_stmt_attr_set() C API函数实现了服务器端光标。服务器端光标允许在服务器端生
- 第一次使用csdn写文章,写得不好还请见谅。(运行环境:python3.6)下了一个带密码的压缩包文件,作为一个刚学python的新手,想着
- 作为一个Oracle数据库开发者或者DBA,在实际工作中经常会遇到这样的问题:试图对库表中的某一列或几列创建唯一索引时,系统提示ORA-01
- 前言:opencv最主要的的功能是用于图像处理,所以图像的概念贯穿了整个opencv,与其相关的核心类就是Mat。像素:图片尺寸以像素为单位
- 如何生成斐波那契數列斐波那契(Fibonacci)數列是一个非常简单的递归数列,除第一个和第二个数外,任意一个数都可由前两个数相加得到。用计
- 只是做笔记,没什么!! 代码如下:--创建测试表 CREATE TABLE [dbo].[Student]( [ID] [int