MySQL 支持的数据类型

一、数值类型

  • MySQL 支持全部标准 SQL 中的数值类型,其中包括严格数值类型(integer、smallint、decimal、numeric),以及近似数值数据类型(float、real、double precision),并在此基础上作了扩展,扩展后增长了 tinyint、mediumint 和 bigint 这 3 种长度不一样的整型,并增长了 bit 类型,用来存放位数据。

1.1 整数类型

  • 1)分类算法

    • 按照取值范围和存储方式不一样,分为 tinyint、smallint、mediumint、int(即 integer)和 bigint 这 5 个类型,分别为 一、二、三、四、8 字节,若是超出类型范围的操做会发生 "Out of range" 错误提示。数据库

      整数类型 字节 最小值(有符号 无符号) 最大值(有符号 无符号) 描述
      tinyint 1 -128,0 127,255 tinyint[(m)] [unsigned] [zerofill]
      smallint 2 -32768,0 32767,65535 smallint[(m)] [unsigned] [zerofill]
      mediumint 3 -8388608,0 8388607,1677215 mediumint[(m)] [unsigned] [zerofill]
      int、integer 4 -2147483648, 0 2147483647,4294967295 int[(m)] [unsigned] [zerofill]
      bigint 8 -9223372036854775808,0 9223372036854775807,18446744073709551615 bigint[(m)] [unsigned] [zerofill]
  • 2)指定显示宽度编程

    • 对于整型数据,MySQL 还支持在类型名称后加 "(m)" 的方式来指定显示宽度,"(m)" 表示该值一共显示 m 位数字,m 又称为精度,若是不显示指定宽度则默认为 int(11)。服务器

      • 通常配合 zerofill 使用,即在数字位数不够的空间用字符 "0" 填满。网络

      • 在设置了宽度限制后,若是插入值大于限制宽度,这时,宽度格式已经没有意义,仍是按照类型的实际精度(如:int 无符号的数值范围为0-255)进行保存,左边不会再填充任何的 "0" 字符。函数

  • 3)属性性能

    • unsigned(无符号)优化

      • 可选属性须要在字段里面保存非负数或者须要较大的上限值时使用。
      • 若是一个列指定为 zerofill,则 MySQL 自动为该列添加 unsigned 属性。
    • auto_increment操作系统

      • 在须要产生惟一标识符或顺序值时使用,即 not null、主键 primary key 或者 unique 键的整数类型。
      • auto_increment 值初始值为 1,增长幅度为 1。
      • 一个表中最多只能有一个 auto_increment 列。

1.2 小数类型

  • 1)分类3d

    • 分为浮点数和定点数。

    • 浮点数通常用于表示含有小数部分的数值,包括 float(单精度)和 double(双精度)。

      浮点数类型 字节 最小值(有符号 无符号) 最大值(有符号 无符号) 描述
      float 4 ± 1.175494351E-38 ± 3.402823466E+38 float[(m, d)] [unsigned] [zerofill]
      double 8 ± 2.2250738585072014E-308 ± 1.7976931348623157E+308 double[(m, d)] [unsigned] [zerofill]
    • 在 MySQL 中,decimal(或 numberic)用来表示定点数,定点数其实是以字符串形式存放,比浮点数更精确,适合用来表示货币等精度高的数据。

      定点数类型 字节 最小值(有符号 无符号) 最大值(有符号 无符号) 描述
      dec(m, d)、decimal(m, d)、numeric(m, d) m + 2 最大取值范围与 double 相同,给定 dec 的有效值范围由 m 和 d 决定 dec[(m, d)] [unsigned] [zerofill]
  • 2)指定显示宽度

    • 浮点数和定点数均可以用类型名称后加 "(m, d)" 的方式来进行表示,"(m, d)" 表示该值一共显示 m 位数字(整数位+小数位),其中 d 位位于小数点后面,m 和 d 又称为精度和标度。

      • 浮点数若是不写精度和标度,则会按照实际精度值显示。
      • 当一个字段被定义为浮点类型后,若是插入数据的精度超过该列定义的实际精度,则插入值会被四舍五入到实际定义的精度值,而后插入,四舍五入的过程不会报错。

      • 定点数若是不写精度和标度,则按照默认值 decimal(10, 0) 来进行操做。
      • 当一个字段被定义为定点数类型后,若是实际插入的数值精度大于实际定义的精度,则 MySQL 会进行警告(默认的 SQLMode 下),可是数据按照实际精度四舍五入后插入;若是 SQLMode 是在 traditional(传统模式)下,则系统会直接报错,致使数据没法插入。

  • 3)使用原则

    • 浮点数存在偏差问题;
    • 对货币等对精度敏感的数据,应该用定点数表示或存储;
    • 在编程中,若是用到浮点数,要特别注意偏差问题,并尽可能避免作浮点数比较;
    • 要注意浮点数中一些特殊值的处理。
  • 4)示例

    > create table t (f float(8, 1));
    
        Query OK, 0 rows affected (0.03 sec)
    
    > desc t;
    
        +-------+------------+------+-----+---------+-------+
        | Field | Type       | Null | Key | Default | Extra |
        +-------+------------+------+-----+---------+-------+
        | f     | float(8,1) | YES  |     | NULL    |       |
        +-------+------------+------+-----+---------+-------+
        1 row in set (0.00 sec)
    
    > insert into t values (1.23456), (1.25456);
    
        Query OK, 1 row affected (0.05 sec)
    
    > select * from t;
    
        +------+
        | f    |
        +------+
        |  1.2 |
        |  1.3 |
        +------+
        2 rows in set (0.00 sec)
    • 从上面的例子中,能够发现对于第一次插入值 1.23456 到 float(8, 1)时,该值被截断,并保存为 1.2,而插入值 1.25456 到 float(8, 1) 时,该值进行了四舍五入而后被截断,并保存为 1.3,因此在选择浮点型数据保存小数时,要注意四舍五入的问题,并尽可能保留足够的小数位,避免存储的数据不许确。
    > create table test (c1 float(10, 2), c2 decimal(10, 2));
    
        Query OK, 0 rows affected (0.03 sec)
    
    > insert into test values (131072.32, 131072.32);
    
        Query OK, 1 row affected (0.02 sec)
    
    > select * from test;
    
        +-----------+-----------+
        | c1        | c2        |
        +-----------+-----------+
        | 131072.31 | 131072.32 |
        +-----------+-----------+
        1 row in set (0.00 sec)
    • 从上面的例子中能够看到,c1 列的值由 131072.32 变成了 131072.31,这是上面的数值在使用单精度浮点数表示时,产生了偏差。这是浮点数特有的问题。所以在精度要求比较高的应用中(好比货币)要使用定点数而不是浮点数来保存数据。

    • 另外,浮点数的比较也是一个广泛存在的问题,在编程中应尽可能避免浮点数的比较,若是非要使用浮点数的比较则最好使用范围比较而不要使用 “==” 比较。

1.3 位类型

  • 1)用途

    • bit(m)位类型用于存放位字段值,

    • bit(m) 能够用来存放多位二进制数,M范围从 1~64,若是不写则默认为 1 位。

  • 2)查看位类型字段

    • 对于位字段,直接使用 select 命令将不会看到结果,可使用 bin(列名)(显示为二进制格式)或者 hex(列名)(显示为十六进制格式)函数进行读取。

      # 查看位类型字段值
      > select bin(id), hex(id) from t2;
      
          +---------+---------+
          | bin(id) | hex(id) |
          +---------+---------+
          | 1       | 1       |
          +---------+---------+
          1 rows in set (0.00 sec)
  • 3)位类型字段插入操做

    • 数据插入 bit 类型字段时,首先转换为二进制,若是位数容许,将成功插入;若是位数小于实际定义的位数,则插入失败。

      # 插入位类型字段值
      > insert into t2 values(2);
      
          Query OK, 1 row affected (0.00 sec)
      
      > select bin(id), hex(id) from t2;
      
          +---------+---------+
          | bin(id) | hex(id) |
          +---------+---------+
          | 1       | 1       |
          | 10      | 2       |
          +---------+---------+
          2 rows in set (0.00 sec)

二、日期时间类型

  • MySQL 中有多种数据类型能够用于日期和时间的表示,不一样的版本可能有所差别。

1.1 日期时间类型

  • 1)分类

    • 每种日期时间类型都有一个有效值范围,若是超出这个范围,在默认的SQLMode下,系统会进行错误提示,并将以零值来进行存储。

      日期时间类型 字节 最小值 最大值 格式 描述
      date 4 1000-01-01 9999-12-31 YYYY-MM-DD date
      time 3 -838:59:59.000000 838:59:59.000000 HH:MM:SS[.fraction] time[(fsp)]
      datetime 8 1000-01-01 00:00:00.000000 9999-12-31 23:59:59.999999 YYYY-MM-DD HH:MM:SS[.fraction] datetime[(fsp)]
      timestamp 4 1970-01-01 00:00:01.000000 UTC 2038-01-19 03:14:07.999999 UTC YYYY-MM-DD HH:MM:SS[.fraction] timestamp[(fsp)]
      year 1 1000 9999 YYYY year(date)
    • timestamp:YYYY-MM-DD HH:MM:SS 格式的字符串

      • 应用场合:须要常常插入或者更新日期为当前系统时间的时候用。
      • 显示宽度固定为 19 个字符。若是想要得到数字值,应在 timestamp 列添加 "+0"。
      • MySQL 规定,timestamp 类型字段一列的默认值为 current_timestamp,若是强制修改,系统会报错。
      • MySQL 只给表中的第一个 timestamp 字段设置默认值为系统日期,若是有第二个 timestamp 类型,则默认值设置为 0 值。
      • 特色:与时区相关。当插入日期时,会先转换为本地时区后存放;而从数据库里面取出时,也一样须要将日期转换为本地时区后显示。这样,两个不一样时区的用户看到的同一个日期多是不同的。
    • year:YYYY

      • 它比 date 占用更少的空间。
      • year 有 2 位或 4 位格式的年,默认是 4 位格式。
      • 在 4 位格式中,容许的值是 1901~2155 和 0000。
      • 在 2 位格式中,容许的值是 70~69,表示从 1970~2069 年。
      • MySQL 以 YYYY 格式显示 year 值(从 5.5.27 开始,2 位格式的 year 已经不被支持)。
  • 2)零值

    • 每种日期时间类型都有一个有效值范围,若是超出这个范围,在默认的 SQLMode 下,系统会进行错误提示,并将以零值来进行存储。

      类型 零值
      date 0000-00-00
      time 00:00:00
      datetime 0000-00-00 00:00:00
      timestamp 0000-00-00 00:00:00
      year 0000
  • 3)timestamp 和 datetime 的区别

    • 时间取值范围不一样

      • timestamp:1970-01-01 08:00:01 到 2038 年的某个时间,时间取值范围较小。
      • datetime :1000-01-01 00:00:00 到 9999-12-31 23:59:59,范围较大。
    • 时间属性的不一样

      • timestamp
        • 表中的第一个 timestamp 列自动设置为系统时间 current_timestamp。若是在一个 timestamp 列中插入 null 或者不明确给该列赋值时,则该列值将自动设置为当前的日期和时间。
        • 当插入的值超出取值范围时,MySQL 认为该值溢出,使用零值 "0000-00-00 00:00:00" 进行填补。
        • timestamp 插入和查询都受当地时区的影响,更能反映出实际的日期。
        • 其属性受 MySQL 版本和服务器 SQLMODE 的影响很大,本章是以 MySQL5.0 为例,具体要参照想对应的 MySQL 帮助文档。
      • datetime
        • 只能反映出插入时当地的时区,其余时区的人查看数据必然会有偏差的。
  • 4)使用原则

    • 根据实际须要选择可以知足应用的最小存储的日期类型。若是应用只须要记录“年份”,那么用 1 个字节来存储的 year 类型彻底能够知足,而不须要用 4 个字节来存储的 date 类型。这样不只仅能节约存储,更可以提升表的操做效率。

    • 若是要记录年月日时分秒,而且记录的年份比较久远,那么最好使用 datetime,而不要使用 timestamp。由于 timestamp 表示的日期范围比 datetime 要短得多。
      若是记录的日期须要让不一样时区的用户使用,那么最好使用 timestamp,由于日期类型中只有它可以和实际时区相对应。

  • 5)示例

    > create table t6(dt datetime);
    
        Query OK, 0 rows affected (0.03 sec)
    
    > insert into t6 values('2007-9-3 12:10:10');
    
        Query OK, 1 row affected (0.00 sec)
    
    > insert into t6 values('2007/9/3 12+10+10');
    
        Query OK, 1 row affected (0.00 sec)
    
    > insert into t6 values('20070903121010');
    
        Query OK, 1 row affected (0.01 sec)
    
    > insert into t6 values(20070903121010);
    
        Query OK, 1 row affected (0.00 sec)
    
    > select * from t6;
    
        +---------------------+
        | dt                  |
        +---------------------+
        | 2007-09-03 12:10:10 |
        | 2007-09-03 12:10:10 |
        | 2007-09-03 12:10:10 |
        | 2007-09-03 12:10:10 |
        +---------------------+
        4 rows in set (0.00 sec)

三、字符串类型

  • MySQL 包括了 char、varchar、binary、varbinary、blob、text、enum 和 set 等多种字符串类型。

    字符串类型 字节 描述及存储要求
    char(m) m 容许长度 0~255 个字节的定长字节字符串
    varchar(m) 容许长度 0~65535 个字节的变长字节字符串,值的长度为 +1 字节
    tinytext 容许长度 0~255 字节,值的长度为 +2 字节
    text 容许长度 0~65535 字节,值的长度为 +2 字节
    mediumtext 容许长度 0~167772150 字节,值的长度为 +3 字节
    longtext 容许长度 0~4294967295 字节,值的长度为 +4 字节
    binary(m) m 容许长度 0~m 个字节的定长字节字符串
    varbinary(m) 容许长度 0~m 个字节的变长字节字符串,值的长度为 +1 字节
    tinyblob 容许长度 0~255 字节,值的长度为 +1 字节
    blob 容许长度 0~65535 字节,值的长度为 +2 字节
    mediumblob 容许长度 0~167772150 字节,值的长度为 +3 字节
    longblob 容许长度 0~4294967295 字节,值的长度为 +4 字节
    enum 取值范围须要在建立表时指定,能够包含 0~65535 个成员
    set 取值范围须要在建立表时指定,能够包含 0~64 个成员

3.1 char 和 varchar 类型

  • 1)相同点

    • char 和 varchar 都用来保存 MySQL 中较短的字符串。
  • 2)区别

    • 存储方式的不一样

      • char 列中的值为固定长度字符串,长度能够为从 0~255 的任何值;
      • varchar 列中的值为可变长度字符串,长度能够指定为 0~255(MySQL 5.0.3 版本之前)或者 65535(MySQL 5.0.3 版本之后)之间的值。
    • 在检索时的处理方式

      • char 删除了尾部的空格,
      • varchar 保留尾部的空格。
    • 最后一行的值只适用 MySQL 运行在非“严格模式”时,若是 MySQL 运行在严格模式,超过列长度的值将不会保存,而且会出现错误提示。

      chart(4) 存储需求 varchar(4) 存储需求
      "" ' ' 4 个字节 '' 1 个字节
      'ab' 'ab ' 4 个字节 'ab' 3 个字节
      'abcd' 'abcd' 4 个字节 'abcd' 5 个字节
      'abcdefgh' 'abcd' 4 个字节 'abcd' 5 个字节
    • 因为 chart 是固定长度的,因此它的处理速度比 varchar 快得多,可是其缺点是浪费存储空间,程序须要对行尾空格进行处理,因此对于那些长度变化不大而且对查询速度有较高要求的数据能够考虑使用 chart 类型来存储。

    • 另外,随着 MySQL 版本的不断升级,varchar 数据类型的性能也在不断改进并提升,因此在许多的应用中,VARCHAR 类型被更多地使用。

  • 3)不一样的存储引擎对 chart 和 varchar 的使用原则

    • MyISAM 存储引擎:建议使用固定长度的数据列代替可变长度的数据列。

    • MEMORY 存储引擎:目前都使用固定长度的数据行存储,所以不管使用 chart 或 varchar 列都没有关系。二者都是做为 chart 类型处理。

    • InnoDB 存储引擎:建议使用 varchar 类型。对于 InnoDB 数据表,内部的行存储格式没有区分固定长度和可变长度列(全部数据行都使用指向数据列值的头指针),所以在本质上,使用固定长度的 chart 列不必定比使用可变长度 varchar 列性能要好。于是,主要的性能因素是数据行使用的存储总量。因为 chart 平均占用的空间多于 varchar,所以使用 varchar 来最小化须要处理的数据行的存储总量和磁盘 I/O 是比较好的。

  • 4)示例

    > create table vc ( v varchar(4), c char(4) );
    
        Query OK, 0 rows affected (0.06 sec)
    
    > insert into vc values ('ab  ', 'ab  ');
    
        Query OK, 1 row affected (0.06 sec)
    
    > select length(v),length(c) from vc;
    
        +-----------+-----------+
        | length(v) | length(c) |
        +-----------+-----------+
        |         4 |         2 |
        +-----------+-----------+
        1 row in set (0.00 sec)
    
    > SELECT concat(v, '+'), concat(c, '+') from vc;
    
        +----------------+----------------+
        | concat(v, '+') | concat(c, '+') |
        +----------------+----------------+
        | ab  +          | ab+            |
        +----------------+----------------+
        1 rows in set (0.00 sec)
    • 显然 char 列最后的空格在作操做时都已经被删除,而 varchar 依然保留空格。

3.2 binary 和 varbinary 类型

  • 1)binary 和 varbinary 相似于 char 和 varchar,不一样的是它们包含二进制字符串而不包含非二进制字符串。

  • 2)示例

    > create table t ( c binary(3) );
    
        Query OK, 0 rows affected (0.03 sec)
    
    > insert into t set c = 'a';
    
        Query OK, 1 row affected (0.04 sec)
    
    > select *, hex(c), c = 'a', c = 'a\0', c = 'a\0\0' from t;
    
        +------+--------+---------+-----------+-------------+
        | c    | hex(c) | c = 'a' | c = 'a\0' | c = 'a\0\0' |
        +------+--------+---------+-----------+-------------+
        | a    | 610000 |       0 |         0 |           1 |
        +------+--------+---------+-----------+-------------+
        1 row in set (0.00 sec)
    • 能够发现,当保存 binary 值时,在值的最后经过填充 "0x00"(零字节)以达到指定的字段定义长度。从上例中看出,对于一个 binary(3) 列,当插入时 "a" 变为 "a\0\0"。

3.3 text 和 blob 类型

  • 1)通常在保存少许字符串的时候,咱们会选择 char 或者 varchar;而在保存较大文本时,一般会选择使用 text 或者 blob。两者之间的主要差异是 blob 能用来保存二进制数据,好比照片;而 text 只能保存字符数据,好比一篇文章或者日记。

  • 2)MySQL 中,text 是一个字符串大型对象,是一个能够存储大量数据的容器,它能容纳不一样大小的数据。text 类型实际是个类型系列(tinytext、text、mediumtext、longtext),除了在存储的最大信息量上不一样外,他们是等同的。

    类型 字节
    tinytext 255B
    text 65K
    mediumtext 16M
    longtext 4G
  • 3)MySQL 中,blob 是一个二进制字符串大型对象,是一个能够存储大量数据的容器,它能容纳不一样大小的数据。blob 类型实际是个类型系列(tinyblob、blob、mediumblob、longblob),除了在存储的最大信息量上不一样外,他们是等同的。

    类型 字节
    tinyblob 255B
    blob 65K
    mediumblob 16M
    longblob 4G
  • 4)blob 和 text 值会引发一些性能问题,特别是在执行了大量的删除操做时

    • 删除操做会在数据表中留下很大的“空洞”,之后填入这些“空洞”的记录在插入的性能上会有影响。为了提升性能,建议按期使用 optimize table 功能对这类表进行碎片整理,避免由于“空洞”致使性能问题。

      > create table t (id varchar(100), context text);
      
          Query OK, 0 rows affected (0.04 sec)
      
      > insert into t values (1, repeat('haha', 100));
      
          Query OK, 1 row affected (0.01 sec)
      
      > insert into t values (2, repeat('haha', 100));
      
          Query OK, 1 row affected (0.01 sec)
      
      > insert into t values (3, repeat('haha', 100));
      
          Query OK, 1 row affected (0.01 sec)
      
      > insert into t select * from t;
      
          Query OK, 3 rows affected (0.07 sec)
          Records: 3  Duplicates: 0  Warnings: 0
      
          ...
      
      > insert into t select * from t;
      
          Query OK, 196608 rows affected (6.19 sec)
          Records: 196608  Duplicates: 0  Warnings: 0
    • 退出到操做系统下,查看表 t 的物理文件大小,这里数据文件显示为 155MB。

      $ du -sh t.*
      16K t.frm
      155Mt.MYD
      8.0Kt.MYI
    • 从表 t 中删除 id 为 “1” 的数据,这些数据占总数据量的 1/3。

      > delete from t where id = 1;
      
          Query OK, 131072 rows affected (3.44 sec)
    • 再退出到操做系统下,查看表 t 的物理文件大小,能够发现,表t的数据文件仍然为155MB,并无由于数据删除而减小。

      $ du -sh t.*
      16K t.frm
      155Mt.MYD
      8.0Kt.MYI
    • 接下来对表进行 optimize(优化)操做。

      # optimize table 表名;
      > optimize table t;
      
          +--------+----------+----------+----------+
          | Table  | Op       | Msg_type | Msg_text |
          +--------+----------+----------+----------+
          | test.t | optimize |   status |       OK |
          +--------+----------+----------+----------+
          1 row in set (2.88 sec)
    • 再次查看表 t 的物理文件大小,能够发现,表的数据文件大大缩小,“空洞”空间已经被回收。

      $ du -sh t.*
      16K t.frm
      104Mt.MYD
      8.0Kt.MYI
  • 5)可使用合成的(Synthetic)索引来提升大文本字段(blob 或 text)的查询性能

    • 简单来讲,合成索引就是根据大文本字段的内容创建一个散列值,并把这个值存储在单独的数据列中,接下来就能够经过检索散列值找到数据行了。可是,要注意这种技术只能用于精确匹配的查询(散列值对于相似“<”或“>=”等范围搜索操做符是没有用处的)。可使用 MD5() 函数生成散列值,也可使用 SHA1() 或 CRC32(),或者使用本身的应用程序逻辑来计算散列值。请记住数值型散列值能够很高效率地存储。一样,若是散列算法生成的字符串带有尾部空格,就不要把它们存储在 char 或 varchar 列中,它们会受到尾部空格去除的影响。合成的散列索引对于那些 blob 或 text 数据列特别有用。用散列标识符值查找的速度比搜索 blob 列自己的速度快不少。

      > create table t (id varchar(100), context blob, hash_value varchar(40));
      
          Query OK, 0 rows affected (0.06 sec)
      
      > insert into t values (1, repeat('beijing', 2), md5(context));
      
          Query OK, 1 row affected (0.09 sec)
      
      > insert into t values (2, repeat('beijing', 2), md5(context));
      
          Query OK, 1 row affected (0.04 sec)
      
      > insert into t values (3, repeat('beijing 2008', 2), md5(context));
      
          Query OK, 1 row affected (0.08 sec)
      
      > select * from t;
      
          +------+--------------------------+----------------------------------+
          | id   | context                  | hash_value                       |
          +------+--------------------------+----------------------------------+
          | 1    | beijingbeijing           | 09746eef633dbbccb7997dfd795cff17 |
          | 2    | beijingbeijing           | 09746eef633dbbccb7997dfd795cff17 |
          | 3    | beijing 2008beijing 2008 | 1c0ddb82cca9ed63e1cacbddd3f74082 |
          +------+--------------------------+----------------------------------+
          3 rows in set (0.00 sec)
    • 若是要查询 context 值为 “beijing 2008beijing 2008” 的记录,则能够经过相应的散列值来查询。

      > select * from t where hash_value = md5(repeat('beijing 2008', 2));
      
          +------+--------------------------+----------------------------------+
          | id   | context                  | hash_value                       |
          +------+--------------------------+----------------------------------+
          | 3    | beijing 2008beijing 2008 | 1c0ddb82cca9ed63e1cacbddd3f74082 |
          +------+--------------------------+----------------------------------+
          1 row in set (0.01 sec)
    • 上面的例子展现了合成索引的用法,因为这种技术只能用于精确匹配,在必定程度上减小了 I/O,从而提升了查询效率。

    • 若是须要对 blob 或者 clob 字段进行模糊查询,MySQL 提供了前缀索引,也就是只为字段的前 n 列建立索引。

      > create index idx_blob on t(context(100));
      
          Query OK, 0 rows affected (0.02 sec)
          Records: 0  Duplicates: 0  Warnings: 0
      
      > desc select * from t where context like 'beijing%' \G;
      
          *************************** 1. row ***************************
                     id: 1
            select_type: SIMPLE
                  table: t
             partitions: NULL
                   type: range
          possible_keys: idx_blob
                    key: idx_blob
                key_len: 103
                    ref: NULL
                   rows: 3
               filtered: 100.00
                  Extra: Using where
          1 row in set, 1 warning (0.00 sec)
    • 能够发现,对 context 前 100 个字符进行模糊查询,就能够用到前缀索引。注意,这里的查询条件中,“%” 不能放在最前面,不然索引将不会被使用。

  • 6)在没必要要的时候避免检索大型的 blob 或 text 值

    • 例如,SELECT * 查询就不是很好的想法,除非可以肯定做为约束条件的 WHERE 子句只会找到所须要的数据行。不然,极可能毫无目的地在网络上传输大量的值。这也是 blob 或 text 标识符信息存储在合成的索引列中对用户有所帮助的例子。用户能够搜索索引列,决定须要的哪些数据行,而后从符合条件的数据行中检索 blob 或 text 值。
  • 7)把 blob 或 text 列分离到单独的表中

    • 在某些环境中,若是把这些数据列移动到第二张数据表中,能够把原数据表中的数据列转换为固定长度的数据行格式,那么它就是有意义的。这会减小主表中的碎片,能够获得固定长度数据行的性能优点。它还可使主数据表在运行 SELECT * 查询的时候不会经过网络传输大量的 blob 或 text 值。

3.4 enum 类型

  • 1)取值范围

    • 是一个字符串对象,它的值范围须要在建立表时指定。
  • 2)存储空间

    • enum 里面能够包含 0~65535 个成员。根据成员的不一样,存储上也有所不一样。

      成员个数 字节
      1~255 1
      255~65535 2
  • 3)示例

    > create table t ( gender enum('M', 'F'));
    
        Query OK, 0 rows affected (0.06 sec)
    
    > insert into t values ('M'), ('1'), ('f'), (null);
    
        Query OK, 4 rows affected (0.06 sec)
        Records: 4  Duplicates: 0  Warnings: 0
    
    > select * from t;
    
        +--------+
        | gender |
        +--------+
        | M      |
        | M      |
        | F      |
        | NULL   |
        +--------+
        4 rows in set (0.00 sec)
    • 从上面的例子中,能够看出 enum 类型是忽略大小写的,在存储 “M”、“f” 时将它们都转成了大写.
    • 还能够看出对于插入不在 enum 指定范围内的值时,并无返回警告,而是插入了 enum('M','F') 的第一个值 “M”,这点用户在使用时要特别注意。
    • 另外,enum 类型只容许从值集合中选取单个值,而不能一次取多个值。

3.5 set 类型

  • 1)取值范围

    • 是一个字符串对象,它的值范围须要在建立表时指定。
  • 2)存储空间

    • set 里面能够包含 0~64 个成员。根据成员的不一样,存储上也有所不一样。

      成员个数 字节
      1~8 1
      9~16 2
      17~24 3
      25~32 4
      33~64 8
  • 3)与 enum 的区别

    • 存储空间

      • set 和 enum 存储空间不一样。
    • 选取成员个数

      • 最主要的区别在于 set 类型一次能够选取多个成员,而 enum 则只能选一个。
    • 插入值选取

      • set 类型能够从容许值集合中选择任意 1 个或多个元素进行组合。
      • enum 只容许从集合值中选取单个值,而不能一次取多个值。
    • 插入值超出范围处理方式

      • 对于超出定义的 set 容许值范围的值将不容许注入到设置的 set 类型列中,发出警告。
      • 对于('a,d,a')这样包含重复成员的集合将只取一次,写入后的结果为 "a,d"。
      • 对于超出定义的 enum 容许范围的值,并不返回警告,而是插入一个在 enum 指定值范围的第一个值。
      • enum 类型只容许从值集合中选取。
  • 4)示例

    > create table t (col set('a', 'b', 'c', 'd'));
    
        Query OK, 0 rows affected (0.11 sec)
    
    > insert into t values ('a,b'), ('a,d,a'), ('a,b'), ('a,c'), ('a');
    
        Query OK, 5 rows affected (0.02 sec)
        Records: 5  Duplicates: 0  Warnings: 0
    
    > select * from t;
    
        +------+
        | col  |
        +------+
        | a,b  |
        | a,d  |
        | a,b  |
        | a,c  |
        | a    |
        +------+
        5 rows in set (0.00 sec)
    • set 类型能够从容许值集合中选择任意 1 个或多个元素进行组合。
    • 对于输入的值只要是在容许值的组合范围内,均可以正确地注入到 set 类型的列中。
    • 对于超出容许值范围的值例如('a,d,f ')将不容许注入到上面例子中设置的 set 类型列中。
    • 而对于('a,d,a')这样包含重复成员的集合将只取一次,写入后的结果为 "a,d"。
相关文章
相关标签/搜索