当前位置:嗨网首页>书籍在线阅读

02-优化表的数据类型

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

表需要使用何种数据类型是需要根据应用来判断的。虽然应用设计的时候需要考虑字段的长度留有一定的冗余,但是不推荐让很多字段都留有大量的冗余,这样既浪费磁盘存储空间,同时在应用程序操作时也浪费物理内存。

在MySQL中,可以使用函数PROCEDURE ANALYSE()对当前应用的表进行分析,该函数可以对数据表中列的数据类型提出优化建议,用户可以根据应用的实际情况酌情考虑是否实施优化。

以下是函数PROCEDURE ANALYSE()的使用方法:

SELECT * FROM tbl_name PROCEDURE ANALYSE();

SELECT * FROM tbl_name PROCEDURE ANALYSE(16,256);

输出的每一列信息都会对数据表中的列的数据类型提出优化建议。以上第二个语句告诉PROCEDURE ANALYSE()不要为那些包含的值多于16个或者256个字节的ENUM类型提出建议。如果没有这样的限制,输出信息可能很长;ENUM定义通常很难阅读。

根据PROCEDURE ANALYSE()函数的输出信息,用户可能会发现,一些表中的字段可以修改为效率更高的数据类型。如果决定改变某个字段的类型,则需要使用ALTER TABLE语句。

下面分析一下表duck_cust的数据类型是否需要优化。

(1)首先创建测试表duck_cust,duck_cust表中记录了客户的一些基本信息:

drop table duck_cust;

CREATE TABLE duck_cust(

cust_num MEDIUMINT AUTO_INCREMENT, --客户编号

cust_title TINYINT, --客户标题号

cust_last CHAR(20) NOT NULL, --客户姓氏

cust_first CHAR(15) NOT NULL, --客户名

cust_suffix ENUM('Jr.', 'II', 'III','IV', 'V', 'M.D.','PhD'), --附加码

cust_add1 CHAR(30) NOT NULL, --客户地址

cust_add2 CHAR(10), --客户地址

cust_city CHAR(18) NOT NULL, --客户所在城市

cust_state CHAR(2) NOT NULL, --客户所在州

cust_zip1 CHAR(5)NOT NULL, --客户邮编

cust_zip2 CHAR(4), --客户邮编

cust_duckname CHAR(25) NOT NULL, --客户名称

cust_duckbday DATE, --客户生日

PRIMARY KEY (cust_num)

)TYPE=MyISAM;

(2)然后生成一些测试数据:

INSERT INTO duck_cust VALUES(NULL, 1, 'Irishlord', 'Red', 'III', '1022 N.E. Sea of Rye', 'A207', 'Seacouver', 'WA', '98601', '3464', 'Netrek Rules', '1967:10:21');

INSERT INTO duck_cust VALUES(NULL, 4, 'Thegreat', 'Vicki', 0, '2004 Singleton Dr.', 0, 'Freedom', 'KS', '67209', '4321', 'Frida Kahlo de Tomayo', '1948:03:21');

INSERT INTO duck_cust VALUES(NULL, 9, 'Montgomery', 'Chantel', 0, '1567 Terra Cotta Way', 0, 'Chicago', 'IL', '89129', '4444', 'Bianca', '1971:07:29');

INSERT INTO duck_cust VALUES(NULL, 7, 'Robert', 'David', 'Sr.', '20113 Open Road Highway', '#6', 'Blacktop', 'AZ', '00606', '1952', 'Harley', '1949:08:00');

INSERT INTO duck_cust VALUES(NULL, 5, 'Kazui', 'Wonko', 'PhD', '42 Cube Farm Lane', 'Gatehouse', 'Vlimpt', 'CA', '45362', 0, 'Fitzwhistle', '1961:12:04');

INSERT INTO duck_cust VALUES(NULL, 6, 'Gashlycrumb', 'Karen', 0, '3113 Picket Fence Lane', 0, 'Fedora', 'VT', '41927', '5698', 'Tess D''urberville', '1948:08:19');

这时,查看一下表结构:

desc duck_cust;

+--------------+--------------------------------+------+------+--------+------------+

| Field | Type | Null | Key | Default | Extra |

+--------------+--------------------------------+------+------+--------+------------+

| cust_num | mediumint(9) | | MUL | 0 | |

| cust_title | tinyint(4) | YES | | NULL | |

| cust_last | char(20) | | | | |

| cust_first | char(15) | | | | |

| cust_suffix |enum('Jr.','II','III','IV','V','M.D.','PhD')| YES | | NULL | |

| cust_add1 | char(30) | | | | |

| cust_add2 | char(10) | YES | | NULL | |

| cust_city | char(18) | | | | |

| cust_state | char(2) | | | | |

| cust_zip1 | char(5) | | | | |

| cust_zip2 | char(4) | YES | | NULL | |

| cust_duckname| char(25) | | | | |

| cust_duckbday| date | YES | | NULL | |

+--------------+---------------------------------+------+------+--------+-----------+

(3)使用PROCEDURE ANALYSE()函数确定要优化的列:

mysql> SELECT * FROM duck_cust PROCEDURE ANALYSE()\G;

1. row

Field_name: sakila.duck_cust.cust_num

Min_value: 1

Max_value: 6

Min_length: 1

Max_length: 1

Empties_or_zeros: 0

Nulls: 0

Avg_value_or_avg_length: 3.5000

Std: 1.7078

Optimal_fieldtype: ENUM('1','2','3','4','5','6') NOT NULL

2. row

从结果中可以看到 test.duck_cust.cust_num 列的 Min_length、Max_length、Avg_value_or_avg_length,根据这些统计值,可以对列进行优化,例如,插入的数据最大长度和最小长度都是 1,所以,可以优化字段 cust_num 为 mediumint(2);同时,上面的结果也给出了优化建议“Optimal_fieldtype: ENUM('1','2','3','4','5','6') NOT NULL”。

看到这个建议读者可能会觉得很奇怪,怎么给出了枚举类型,而不是我们预期的整型?因为这时分析的测试表记录数太少,使得cust_name的唯一值太少,因此函数觉得用枚举类型会更合理。如果是对一个大表进行分析,提出的建议会更准确。

根据给出的统计信息和优化建议,可以使用如下语句进行字段类型的更改:

mysql> alter table duck_cust modify cust_num mediumint(2);

Query OK, 6 rows affected (0.03 sec)

Records: 6 Duplicates: 0 Warnings: 0