选择合适的数据类型

在使用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. __block 和__weak 区别及使用

    API Reference对__block变量修饰符有如下几处解释: //A powerful feature of blocks is that they can modify variables ...

  2. Mysql备份工具比较

    Mysql备份工具比较 大 | 中 | 小 [ 2012/12/25 12:10 | by Sonic ] 1. 使用automysqlbackup http://sourceforge.net/pr ...

  3. Java中有几种类型的流?以及常见的实现类都有哪些?

    Java中有几种类型的流?以及常见的实现类都有哪些? 首先应该从两个角度来看: 从输入输出方面来讲:       Java中有输入流和输出流 从流的编码方式上来讲:    Java中有字节流和字符流 ...

  4. c#的bug?

    在群里面有人提出了这么一个诡异的问题,请问15.5%3.1=? 然后,我就去看了看,因为他们说结果是3.1!!!

  5. linux下1号进程的前世(kthread_init)今生(init)

    参考: 1.  Linux下1号进程的前世(kernel_init)今生(init进程)----Linux进程的管理与调度(六) 2. linux挂载根文件系统过程 3. BusyBox init工作 ...

  6. 你设计的应用是IO依赖型还是CPU依赖型?

    这个话题可能看起来非常枯燥,但它对mysql的性能优化非常重要. 其实我在MYSQL 咨询工作中无时无刻接不在接触这类问题. IO工作负载与cpu依赖全然不同,尤其是当你的工作集(通常仅仅有数据库的一 ...

  7. String类和StringBuilder

    1,首先,明确一点,String对象是不可变的,这个不可变的意思是说:任何看起来修改String值的方法,实际上都是创建了一个新的String对象. 2,String对+号操作符进行了重载,而这个重载 ...

  8. 解决android studio引用远程仓库下载慢(转)

    解决android studio引用远程仓库下载慢(JCenter下载慢) 第一种方法 使用开源中国的maven库 阿里云的(速度飞快):http://maven.aliyun.com/nexus/c ...

  9. CSS3之body背景图平铺

    你再也不需要因为屏幕大小不同而去选择多张图片作为背景图了,css3教你做人: body { background: url('xx.jpg')top center no-repeat; backgro ...

  10. Linq to SQL 语法查询(子查询 & in操作 & join )

    var 子查询 = from c in ctx.Customers                    where                        (from o in ctx.Ord ...