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"。
相關文章
相關標籤/搜索