选择合适的数据类型

在使用MySQL创建数据表的时候会遇到一个问题,如何为字段选择合适的数据类型.比如创建一个员工信息表,每个字段都可以用很多种类型来定义,

int,char,float等等.

char和varchar

char和varchar都是用来存储字符串类型的数据,但是他们保存和检索的方式不一样.char属于固定长度的字符类型,二varchar属于可变成的字符类型

值  char(4) 存储需求 varchar(4) 存储需求
'' '   ' 4个字节 ''  1个字节
'ab' 'ab ' 4个字节 'ab' 3个字节
'abcd' 'abcd' 4个字节 'abcd' 5个字节
'abcdefg' 'abcd' 4个字节 'abcd' 5个字节

由于char是固定长度的,所以它的处理速度比varchar快得多,但是其缺点是浪费存储空间,程序需要对尾行空格进行处理,所以对那些变化不打并且查询速度有较高的要求的数据可以考虑使用char类型来存储

  在mysql中,不同的存储引擎对char和varchar的使用原则有所不同

  • MyISAM存储引擎

    • 建议使用固定长度的数列代替可变长度的数据列
  • InnoDB存储引擎
    • 建议使用varchar类型,对于InnnoDB数据表,内部的行存储格式没有区分固定长度和可变长度,因此使用char列不一定比可变长度的varchar性能好
    • 由于char平均占用空间多余varchar,因此varchar来UI消化需要处理的数据航的存储总量和磁盘I/O是比较好的.

TEXT和BLOB

介绍

在选择大文本的时候我们会优先选择text类型或者blob比如文章.

那么TEXT和BLOB最主要的区别是 BLOB能用来保存二进制数据比如照片.而text智能保存字符串数据,比如文章和日记.

根据存储的文本长度不同和存储的字节不同我们可以使用

MEDIUMTEXT,LONGTEXT和MUDIUMBLOB,LONGBLOB

常见问题

空洞问题

BLOB和text在执行了大量的删除操作时,会留下很大的'空洞',以后填入这些'空洞'的记录在插入的性能上回有影响.为了提高性能,建议使用OPTIMIZE TABLE功能对类表进行碎片整理,

避免空洞带来的性能问题

空洞例子:

CREATE TABLE t (
id VARCHAR(100),
context TEXT
);
INSERT INTO t VALUES(1,repeat('haha',100));
INSERT INTO t VALUES(2,repeat('haha',100));
INSERT INTO t VALUES(3,repeat('haha',100));
insert into t select * from t;
insert into t select * from t;
.....
insert into t select * from t;

这时候文件的大小为:

删除id=1的数据,那么就是删除了1/3的数据:

mysql> delete from t where id=1;
Query OK, 32768 rows affected (0.63 sec)

再看文件大小,我们可以看到文件大小还是96MB,这就形成了空洞.

我们用OPTIMIZE进行优化:

mysql> optimize table t;

此时我们再看文件,已经变成了60MB,文件大大的缩小了,说明'空洞被收回了'

文件索引

使用合成索引来提高大文本字段的查询性能:

合成索引就是根据大文本的字段的内容建立一个散列值,并且把这个值存储在单独的数据列中,接下来可以通过检索散列值来找到数据.

但是,要注意这种技术只能用于精确匹配(对于< >=等范围搜索是没有用的)

可以使用MD5()函数来生成散列值.

下面介绍一下合成索引的方法:

CREATE TABLE t (
id VARCHAR(100),
context BLOB,
hash_value char(32)
);
INSERT INTO t VALUES(1,repeat('beijing',2),MD5(context)); INSERT INTO t VALUES(1,repeat('beijing2008',2),MD5(context)); mysql> select * from t where hash_value=md5(repeat('beijing2008',2));
+------+------------------------+----------------------------------+
| id | context | hash_value |
+------+------------------------+----------------------------------+
| 1 | beijing2008beijing2008 | 0fe88accc8741a9d1bc323bd286866bb |
+------+------------------------+----------------------------------+

由于这种技术只能用于精确匹配,从一定程度上减少了I/O,提高了查询效率.如果需要对BLOB字段进行模糊查询,MYsql提供了前缀索引,也就是只为字段的前n列创建索引

create index idx_blob on t(context(100));
mysql> desc select * from t where context like "beijing%" \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
type: range
possible_keys: idx_blob
key: idx_blob
key_len: 103
ref: NULL
rows: 2
Extra: Using where
1 row in set (0.04 sec)

对context的前100个字符进行模糊查询,就可以用前缀索引.

注意这里的%不能放在前面,否则不能命中索引

避免使用select *

不要用select * 检索大型的BLOB或者TEXT值

除非能够确定约束条件where只会找到需要的数据,否则很可能毫无目的在网络上传输大量的值.

用户可以用搜索索引列,决定需要的那些数据行,然后从符合条件的数据中检索BLOB或者TEXT

分表

水平分表,在某些环境中,如果把这些大型的列数据移动到第二章表数据中,那么把原数据表中的数据列转换成固定长度的数据行格式,

那么它就是有意义的.这会减少表中的碎片,可以得到固定长度的性能优势.

浮点数和定点数

在MYSQL中用float,double来标识浮点数.当一个字段被定义浮点类型后,如果插入的数据精度超过该列定义的实际精度,那么会采取四舍五入的办法来得到实际的值.

定点数不同于浮点数,他是用字符串的形式存存放的,所以插入的实际值精度大于实际定义的精度,如果在传统模式下,会直接报错,不能插入数据.

CREATE TABLE test(c1 float(10,2),c2 decimal(10,2));

INSERT INTO text VALUES(131072.32,131072.32);

mysql> select * from test;
+-----------+-----------+
| c1 | c2 |
+-----------+-----------+
| 131072.31 | 131072.32 |
+-----------+-----------+

可以看到c1列的值从131072.32 变成了131072.31,这是上面的数值在使用单精度浮点数表示时,产生了误差.

注意:

  • 浮点数存在误差问题
  • 对货币等对精度要求比较高的数据,应该用定点数表示或存储
  • 在变成中,如果用到浮点数,要特别注意误差问题,尽量避免做浮点数比较

日期类型的选择

  • 根据实际需要选择能够满足的最小存储的日期类型,如果只需要记录年,那么用一个字节来存储的YEAR类型就而已满足.而不需要用4个字节的date,不仅节省空间,还提高查询效率
  • 如果要记录年月日时分秒,并记录比较久远,那么最好使用datetime,不要使用timestamp
  • 如果记录的日期需要不同的时区的用户使用,那么最好使用timestamp,因为日期类型中,只有他能够和实际时区相对应

mysql设计表结构数据类型的选择的更多相关文章

  1. navicat如何导出mysql数据表结构

    我们在创建数据库时会对字段进行设置,比如类型.长度等,如果字段多的话一个个设置非常麻烦,可以从其他地方已有的表导入数据表结构,怎么操作呢?我们拿navicat导出mysql数据表结构为例: 1.点击“ ...

  2. 用户中心mysql数据库表结构的脚本

    /* Navicat MySQL Data Transfer Source Server : rm-m5e3xn7k26i026e75o.mysql.rds.aliyuncs.com Source S ...

  3. mysql数据库表结构导出

    mysql数据库表结构导出 命令行下具体用法如下: mysqldump -u用戶名 -p密码 -d 数据库名 表名 > 脚本名; 导出整个数据库结构和数据 mysqldump -h localh ...

  4. mysql对比表结构对比同步,sqlyog架构同步工具

    mysql对比表结构对比同步,sqlyog架构同步工具 对比后的结果示例: 执行后的结果示例: 点击:"另存为(S)" 按钮可以把更新sql导出来.

  5. MySQL复制表结构表数据

    MySQL复制表结构 表数据 1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表这种方法会将oldtable中所有的内容都拷贝过来,当然我们可以用delete ...

  6. MySQL 查看表结构

    mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名; use information_s ...

  7. mysql查看表结构命令

    mysql查看表结构命令 mysql查看表结构命令,如下: desc 表名;show columns from 表名;describe 表名;show create table 表名; use inf ...

  8. Mysql 复制表结构 及其表的内容

    顺便转一下Mysql复制表结构.表数据的方法: 1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表 这种方法会将oldtable中所有的内容都拷贝过来,当然我们 ...

  9. mysql查看表结构,字段等命令

    mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名;

随机推荐

  1. JS的同步加载、异步加载

    在使用js展开式菜单时,发现只有加载完页面包含的js文件时,展开菜单才能折叠起来. 查找了一下原因:是因为js页面加载使用的是同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当当前 ...

  2. 客户端与服务端Post报文构造请求及Http Post与Get请求方法

    客户端 namespace Client.Controllers { public class HomeController : Controller { // // GET: /Home/ publ ...

  3. JAVA WEB项目开发案例精粹

    http://www.blogjava.net/zongbao/archive/2012/07/24/383884.htmlJAVA WEB项目开发案例精粹.pdf main Alt + / => ...

  4. 无序列表li横向排列

    一.横向两列方式排列: 在网页中,很多地方都会用到无序列表横向排列的形式,通常的写法都是使得li的css样式设置为:float:left的形式即可,li会依次从最左边开始并列对齐, 例如: HTML中 ...

  5. Git实战(四)状态转换

    上次的Git实战(三)环境搭建博文.我们大致解说了一下git的环境安装,今天我们解说一下Git的状态转换. 学习版本号控制工具.对工具进行版本号控制之间的状态转换很重要.毕竟Git仅仅是一个工具.假设 ...

  6. C++语言基础(11)-多态

    一.产生背景 先看下面的例子: #include <iostream> using namespace std; //基类People class People{ public: Peop ...

  7. PHP输出xls文件

    PHP输出xls文件 标签: phpexcelxmlcsvborderheader 2008-11-17 09:33 2611人阅读 评论(0) 收藏 举报  分类: WebDev(9)  版权声明: ...

  8. MySQL和hive对比表结构脚本

    #!/bin/bash source /etc/profile runlog='/tmp/zewei/check_schema_log' hive_database_schema=/tmp/hive_ ...

  9. 敏捷开发 scrum管理

    项目准备阶段 1.产品经理将整体项目拆分成不同的单独模块,每个模块尽量细化到能够自成一体.例如app的登录注册模块,不能仅仅就是登录注册这两个界面,而是要将所有与这有关的需求整合到一块.要达到的效果就 ...

  10. iOS10 获取系统通讯录新方法

    #import <ContactsUI/ContactsUI.h> 遵循代理 CNContactPickerDelegate 调用通讯录 如果在iOS10的机器上调用以前的ABPeople ...