MySQL 你可能忽視的選擇問題

咱們在 MySQL 入門篇主要介紹了基本的 SQL 命令、數據類型和函數,在局部以上知識後,你就能夠進行 MySQL 的開發工做了,可是若是要成爲一個合格的開發人員,你還要具有一些更高級的技能,下面咱們就來探討一下 MySQL 都須要哪些高級的技能mysql

MySQL 存儲引擎

存儲引擎概述

數據庫最核心的一點就是用來存儲數據,數據存儲就避免不了和磁盤打交道。那麼數據以哪一種方式進行存儲,如何存儲是存儲的關鍵所在。因此存儲引擎就至關因而數據存儲的發動機,來驅動數據在磁盤層面進行存儲。算法

MySQL 的架構能夠按照三層模式來理解sql

存儲引擎也是 MySQL 的組建,它是一種軟件,它所能作的和支持的功能主要有數據庫

  • 併發
  • 支持事務
  • 完整性約束
  • 物理存儲
  • 支持索引
  • 性能幫助

MySQL 默認支持多種存儲引擎,來適用不一樣數據庫應用,用戶能夠根據須要選擇合適的存儲引擎,下面是 MySQL 支持的存儲引擎緩存

  • MyISAM
  • InnoDB
  • BDB
  • MEMORY
  • MERGE
  • EXAMPLE
  • NDB Cluster
  • ARCHIVE
  • CSV
  • BLACKHOLE
  • FEDERATED

默認狀況下,若是建立表不指定存儲引擎,會使用默認的存儲引擎,若是要修改默認的存儲引擎,那麼就能夠在參數文件中設置 default-table-type,可以查看當前的存儲引擎安全

show variables like 'table_type';
複製代碼

奇怪,爲何沒有了呢?網上求證一下,在 5.5.3 取消了這個參數數據結構

能夠經過下面兩種方法查詢當前數據庫支持的存儲引擎架構

show engines \g
複製代碼

在建立新表的時候,能夠經過增長 ENGINE 關鍵字設置新建表的存儲引擎。併發

create table cxuan002(id int(10),name varchar(20)) engine = MyISAM;
複製代碼

上圖咱們指定了 MyISAM 的存儲引擎。函數

若是你不知道表的存儲引擎怎麼辦?你能夠經過 show create table 來查看

若是不指定存儲引擎的話,從MySQL 5.1 版本以後,MySQL 的默認內置存儲引擎已是 InnoDB了。建一張表看一下

如上圖所示,咱們沒有指定默認的存儲引擎,下面查看一下表

能夠看到,默認的存儲引擎是 InnoDB

若是你的存儲引擎想要更換,可使用

alter table cxuan003 engine = myisam;
複製代碼

來更換,更換完成後回顯示 0 rows affected ,但其實已經操做成功

咱們使用 show create table 查看一下表的 sql 就知道

存儲引擎特性

下面會介紹幾個經常使用的存儲引擎以及它的基本特性,這些存儲引擎是 **MyISAM、InnoDB、MEMORY 和 MERGE **

MyISAM

在 5.1 版本以前,MyISAM 是 MySQL 的默認存儲引擎,MyISAM 併發性比較差,使用的場景比較少,主要特色是

  • 不支持事務操做,ACID 的特性也就不存在了,這一設計是爲了性能和效率考慮的。

  • 不支持外鍵操做,若是強行增長外鍵,MySQL 不會報錯,只不過外鍵不起做用。

  • MyISAM 默認的鎖粒度是表級鎖,因此併發性能比較差,加鎖比較快,鎖衝突比較少,不太容易發生死鎖的狀況。

  • MyISAM 會在磁盤上存儲三個文件,文件名和表名相同,擴展名分別是 .frm(存儲表定義).MYD(MYData,存儲數據)MYI(MyIndex,存儲索引)。這裏須要特別注意的是 MyISAM 只緩存索引文件,並不緩存數據文件。

  • MyISAM 支持的索引類型有 全局索引(Full-Text)B-Tree 索引R-Tree 索引

    Full-Text 索引:它的出現是爲了解決針對文本的模糊查詢效率較低的問題。

    B-Tree 索引:全部的索引節點都按照平衡樹的數據結構來存儲,全部的索引數據節點都在葉節點

    R-Tree索引:它的存儲方式和 B-Tree 索引有一些區別,主要設計用於存儲空間和多維數據的字段作索引,目前的 MySQL 版本僅支持 geometry 類型的字段做索引,相對於 BTREE,RTREE 的優點在於範圍查找。

  • 數據庫所在主機若是宕機,MyISAM 的數據文件容易損壞,並且難以恢復。

  • 增刪改查性能方面:SELECT 性能較高,適用於查詢較多的狀況

InnoDB

自從 MySQL 5.1 以後,默認的存儲引擎變成了 InnoDB 存儲引擎,相對於 MyISAM,InnoDB 存儲引擎有了較大的改變,它的主要特色是

  • 支持事務操做,具備事務 ACID 隔離特性,默認的隔離級別是可重複讀(repetable-read)、經過MVCC(併發版本控制)來實現的。可以解決髒讀不可重複讀的問題。
  • InnoDB 支持外鍵操做。
  • InnoDB 默認的鎖粒度行級鎖,併發性能比較好,會發生死鎖的狀況。
  • 和 MyISAM 同樣的是,InnoDB 存儲引擎也有 .frm文件存儲表結構 定義,可是不一樣的是,InnoDB 的表數據與索引數據是存儲在一塊兒的,都位於 B+ 數的葉子節點上,而 MyISAM 的表數據和索引數據是分開的。
  • InnoDB 有安全的日誌文件,這個日誌文件用於恢復因數據庫崩潰或其餘狀況致使的數據丟失問題,保證數據的一致性。
  • InnoDB 和 MyISAM 支持的索引類型相同,但具體實現由於文件結構的不一樣有很大差別。
  • 增刪改查性能方面,果執行大量的增刪改操做,推薦使用 InnoDB 存儲引擎,它在刪除操做時是對行刪除,不會重建表。

MEMORY

MEMORY 存儲引擎使用存在內存中的內容來建立表。每一個 MEMORY 表實際只對應一個磁盤文件,格式是 .frm。 MEMORY 類型的表訪問速度很快,由於其數據是存放在內存中。默認使用 HASH 索引

MERGE

MERGE 存儲引擎是一組 MyISAM 表的組合,MERGE 表自己沒有數據,對 MERGE 類型的表進行查詢、更新、刪除的操做,其實是對內部的 MyISAM 表進行的。MERGE 表在磁盤上保留兩個文件,一個是 .frm 文件存儲表定義、一個是 .MRG 文件存儲 MERGE 表的組成等。

選擇合適的存儲引擎

在實際開發過程當中,咱們每每會根據應用特色選擇合適的存儲引擎。

  • MyISAM:若是應用程序一般以檢索爲主,只有少許的插入、更新和刪除操做,而且對事物的完整性、併發程度不是很高的話,一般建議選擇 MyISAM 存儲引擎。
  • InnoDB:若是使用到外鍵、須要併發程度較高,數據一致性要求較高,那麼一般選擇 InnoDB 引擎,通常互聯網大廠對併發和數據完整性要求較高,因此通常都使用 InnoDB 存儲引擎。
  • MEMORY:MEMORY 存儲引擎將全部數據保存在內存中,在須要快速定位下可以提供及其迅速的訪問。MEMORY 一般用於更新不太頻繁的小表,用於快速訪問取得結果。
  • MERGE:MERGE 的內部是使用 MyISAM 表,MERGE 表的優勢在於能夠突破對單個 MyISAM 表大小的限制,而且經過將不一樣的表分佈在多個磁盤上, 能夠有效地改善 MERGE 表的訪問效率。

選擇合適的數據類型

咱們會常常碰見的一個問題就是,在建表時如何選擇合適的數據類型,一般選擇合適的數據類型可以提升性能、減小沒必要要的麻煩,下面咱們就來一塊兒探討一下,如何選擇合適的數據類型。

CHAR 和 VARCHAR 的選擇

char 和 varchar 是咱們常常要用到的兩個存儲字符串的數據類型,char 通常存儲定長的字符串,它屬於固定長度的字符類型,好比下面

char(5) 存儲字節
'' ' ' 5個字節
'cx' 'cx ' 5個字節
'cxuan' 'cxuan' 5個字節
'cxuan007' 'cxuan' 5個字節

能夠看到,無論你的值寫的是什麼,一旦指定了 char 字符的長度,若是你的字符串長度不夠指定字符的長度的話,那麼就用空格來填補,若是超過字符串長度的話,只存儲指定字符長度的字符。

這裏注意一點:若是 MySQL 使用了非 嚴格模式的話,上面表格最後一行是能夠存儲的。若是 MySQL 使用了 嚴格模式 的話,那麼表格上面最後一行存儲會報錯。

若是使用了 varchar 字符類型,咱們來看一下例子

varchar(5) 存儲字節
'' '' 1個字節
'cx' 'cx ' 3個字節
'cxuan' 'cxuan' 6個字節
'cxuan007' 'cxuan' 6個字節

能夠看到,若是使用 varchar 的話,那麼存儲的字節將根據實際的值進行存儲。你可能會疑惑爲何 varchar 的長度是 5 ,可是卻須要存儲 3 個字節或者 6 個字節,這是由於使用 varchar 數據類型進行存儲時,默認會在最後增長一個字符串長度,佔用1個字節(若是列聲明的長度超過255,則使用兩個字節)。varchar 不會填充空餘的字符串。

通常使用 char 來存儲定長的字符串,好比身份證號、手機號、郵箱等;使用 varchar 來存儲不定長的字符串。因爲 char 長度是固定的,因此它的處理速度要比 VARCHAR 快不少,可是缺點是浪費存儲空間,可是隨着 MySQL 版本的不斷演進,varchar 數據類型的性能也在不斷改進和提升,因此在許多應用中,VARCHAR 類型更多的被使用。

在 MySQL 中,不一樣的存儲引擎對 CHAR 和 VARCHAR 的使用原則也有不一樣

  • MyISAM:建議使用固定長度的數據列替代可變長度的數據列,也就是 CHAR
  • MEMORY:使用固定長度進行處理、CHAR 和 VARCHAR 都會被看成 CHAR 處理
  • InnoDB:建議使用 VARCHAR 類型

TEXT 與 BLOB

通常在保存較少的文本的時候,咱們會選擇 CHAR 和 VARCHAR,在保存大數據量的文本時,咱們每每選擇 TEXT 和 BLOB;TEXT 和 BLOB 的主要差異是 BLOB 可以保存二進制數據;而 TEXT 只能保存字符數據,TEXT 往下細分有

  • TEXT
  • MEDIUMTEXT
  • LONGTEXT

BLOB 往下細分有

  • BLOB
  • MEDIUMBLOB
  • LONGBLOB

三種,它們最主要的區別就是存儲文本長度不一樣和存儲字節不一樣,用戶應該根據實際狀況選擇知足需求的最小存儲類型,下面主要對 BLOB 和 TEXT 存在一些問題進行介紹

TEXT 和 BLOB 在刪除數據後會存在一些性能上的問題,爲了提升性能,建議使用 OPTIMIZE TABLE 功能對錶進行碎片整理。

也可使用合成索引來提升文本字段(BLOB 和 TEXT)的查詢性能。合成索引就是根據大文本(BLOB 和 TEXT)字段的內容創建一個散列值,把這個值存在對應列中,這樣就可以根據散列值查找到對應的數據行。通常使用散列算法好比 md5() 和 SHA1() ,若是散列算法生成的字符串帶有尾部空格,就不要把它們存在 CHAR 和 VARCHAR 中,下面咱們就來看一下這種使用方式

首先建立一張表,表中記錄 blob 字段和 hash 值

向 cxuan005 中插入數據,其中 hash 值做爲 info 的散列值。

而後再插入兩條數據

插入一條 info 爲 cxuan005 的數據

若是想要查詢 info 爲 cxuan005 的數據,能夠經過查詢 hash 列來進行查詢

這是合成索引的例子,若是要對 BLOB 進行模糊查詢的話,就要使用前綴索引。

其餘優化 BLOB 和 TEXT 的方式:

  • 非必要的時候不要檢索 BLOB 和 TEXT 索引
  • 把 BLOB 或 TEXT 列分離到單獨的表中。

浮點數和定點數的選擇

浮點數指的就是含有小數的值,浮點數插入到指定列中超過指定精度後,浮點數會四捨五入,MySQL 中的浮點數指的就是 floatdouble,定點數指的是 decimal,定點數可以更加精確的保存和顯示數據。下面經過一個示例講解一下浮點數精確性問題

首先建立一個表 cxuan006 ,只爲了測試浮點數問題,因此這裏咱們選擇的數據類型是 float

而後分別插入兩條數據

而後執行查詢,能夠看到查詢出來的兩條數據執行的舍入不一樣

爲了清晰的看清楚浮點數與定點數的精度問題,再來看一個例子

先修改 cxuan006 的兩個字段爲相同的長度和小數位數

而後插入兩條數據

執行查詢操做,能夠發現,浮點數相較於定點數來講,會產生偏差

日期類型選擇

在 MySQL 中,用來表示日期類型的有 DATE、TIME、DATETIME、TIMESTAMP,在

138 張圖帶你 MySQL 入門

這篇文中介紹過了日期類型的區別,咱們這裏就再也不闡述了。下面主要介紹一下選擇

  • TIMESTAMP 和時區相關,更能反映當前時間,若是記錄的日期須要讓不一樣時區的人使用,最好使用 TIMESTAMP。
  • DATE 用於表示年月日,若是實際應用值須要保存年月日的話就可使用 DATE。
  • TIME 用於表示時分秒,若是實際應用值須要保存時分秒的話就可使用 TIME。
  • YEAR 用於表示年份,YEAR 有 2 位(最好使用4位)和 4 位格式的年。 默認是4位。若是實際應用只保存年份,那麼用 1 bytes 保存 YEAR 類型徹底能夠。不但可以節約存儲空間,還能提升表的操做效率。

MySQL 字符集

下面來認識一下 MySQL 字符集,簡單來講字符集就是一套文字符號和編碼、比較規則的集合。1960 年美國標準化組織 ANSI 發佈了第一個計算機字符集,就是著名的 ASCII(American Standard Code for Information Interchange) 。自從 ASCII 編碼後,每一個國家、國際組織都研究了一套本身的字符集,好比 ISO-8859-1GBK 等。

可是每一個國家都使用本身的字符集爲移植性帶來了很大的困難。因此,爲了統一字符編碼,國際標準化組織(ISO) 指定了統一的字符標準 - Unicode 編碼,它容納了幾乎全部的字符編碼。下面是一些常見的字符編碼

字符集 是否認長 編碼方式
ASCII 單字節 7 位編碼
ISO-8859-1 單字節 8 位編碼
GBK 雙字節編碼
UTF-8 1 - 4 字節編碼
UTF-16 2 字節或 4 字節編碼
UTF-32 4 字節編碼

對數據庫來講,字符集是很重要的,由於數據庫存儲的數據大多數都是各類文字,字符集對數據庫的存儲、性能、系統的移植來講都很是重要。

MySQL 支持多種字符集,可使用 show character set; 來查看全部可用的字符集

或者使用

select character_set_name, default_collate_name, description, maxlen from information_schema.character_sets;
複製代碼

來查看。

使用 information_schema.character_set 來查看字符集和校對規則。

相關文章
相關標籤/搜索