武漢加油!!!
背景
數據庫是什麼? 這個問題大家都知道吧, 用來存放數據的, 生活中你在銀行中存的金額, 或者一個戶籍所中存放的戶籍以及個人信息, 在比如一個學校的學生信息等等, 這些都存放在我們的數據庫裏面. 對不數據庫中的數據一般採用一些DML語句
(insert, update, delete)來進行數據操作. 想要查看數據庫裏面的數據使用select語句進行數據的查詢.
對於數據在數據庫裏面的存放, 可以簡單理解爲類似Excel表格
, 表格裏面每一行代表一條數據. 一個Sheet頁
來代表一類數據.
一個例子
現在我們有一張excel表格, 裏面存放了一個學校的學生信息, 包含學號, 姓名, 班級,年級等等信息
- 如果, 如果這張表裏面只存放了較少的數據(
幾十條, 或者十幾條
), 那現在讓你找到關於張三學生的信息
, 我們便開始從上到下或者從下到上開始瀏覽每一行數據, 直到找到張三
, 便完成了數據的查詢. - 但是, 數據量大了, 這個excel存放了成千上萬條數據, 再讓你找出來張三, 你還是需要從上到下, 或者從下到上開始找
張三
, 這一次因爲數據變多了, 導致你可能一眼找到張三, 可能要瀏覽一段時間才能找出來張三.
上面的例子, 便是一個數據查詢經典的問題, 那麼如何解決這個問題呢? 通過索引即可
另一個例子
張三買了一本書《鋼鐵是怎樣煉成的》看完了一遍之後, 時隔半年突然想起了人最寶貴的東西是生命.生命對人來說只有一次.因此,人的一生應當這樣度過:當一個人回首往事時,不因虛度年華而悔恨,也不因碌碌無爲而羞愧..
但是忘記了後半句, 只記得是在某一章(我記得是好像是在整書結尾來着
), 然後張三通過目錄找到了這一章, 很快便從這一章裏面找到了這句話的後半句.
那麼這個目錄便可以理解爲一個索引
, 最主要的目的就是加快查詢的速度
索引
在上面通過兩個生活中的例子, 描述了
索引是什麼以及索引的功能
, 在我們的數據庫中, 道理也是一樣的,
索引
: 索引用於快速找出在某個列中有一特定值的行,不使用索引,MySQL必須從第一條記錄開始讀完整個表,直到找出相關的行,表越大,查詢數據所花費的時間就越多,如果表中查詢的某列有一個索引,MySQL能夠快速到達一個位置去搜索數據文件,那麼將會節省很大一部分時間
索引存儲類型
: 當把某一列作爲索引的時候, 數據查詢就變成了 先找索引, 再根據索引找這一條數據. 爲了進一步提升所以的查詢效率, 就引入了一些數據結構算法來提升效率MySQL中的索引的存儲類型有兩種:BTREE、HASH。 也就是用樹或者Hash值來存儲該字段
優點
:- 理論上任何字段類型都可以被建立索引.
- 顯著提高查詢的速度
缺點
:- 索引的創建需要消耗時間, 並且索引也需要維護, 維護的也會增加工作量
何時使用
:- 對於經常作爲查詢條件的字段優先建立索引
- 數據經常變動的表避免過多建立索引
- 數據量較小的表, 儘可能不去建立索引, 因爲由於數據較少可能查詢全部花費的時間比遍歷索引時間更少.
存儲引擎
對於Mysql首先要知道的是:索引是在存儲引擎中實現的,也就是說不同的存儲引擎,會使用不同的索引
, 所以先來認識一下mysql幾種存儲引擎.
MySQL有一個被稱爲“Pluggable Storage Engine Architecture”(可替換存儲引擎架構)的特性,也就意味着MySQL數據庫提供了多種存儲引擎。用戶可以根據不同的需求爲數據表選擇不同的存儲引擎,用戶也可以根據自己的需要編寫自己的存儲引擎。
存儲引擎種類
引擎名稱 | 解釋 |
---|---|
CSV | 基於 CSV 格式文件存儲數據(應用於跨平臺的數據交換) |
Archive | 將數據壓縮後進行存儲,非常適合存儲大量的獨立的,作爲歷史記錄的數據,但是隻能進行插入 和查詢 操作 |
Falcon | 一種新的存儲引擎,支持事物處理 |
Memory | 內存存儲引擎,擁有極高的插入,更新和查詢效率。但是會佔用和數據量成正比的內存空間。只在內存上保存數據,意味着數據可能會丟失 |
MRG_MyISAM(MERGE) | 將多個表聯合成一個表使用,在超大規模數據存儲時很有用 |
ISAM | MyISAM的前身,MySQL5.0以後不再默認安裝 |
MyISAM | 高速引擎,擁有較高的插入,查詢速度,但不支持事務 |
InnoDB | 5.5版本後MySQL的默認數據庫,支持事務和行級鎖定,比MyISAM處理速度稍慢 |
表格中列舉的是Mysql支持的幾種存儲引擎的, 其中後兩種是生產開發中使用最多的方案, 下面我們重點介紹一下.
MyISAM引擎
這種引擎又可以細分爲動態
, 靜態
, 壓縮
三種:
-
靜態MyISAM
:如果數據表中的各數據列的長度都是預先固定好的,服務器將自動選擇這種表類型。因爲 數據表中每一條記錄所佔用的空間都是一樣的,所以這種表存取和更新的效率非常高。 -
動態MyISAM
:如果數據表中出現varchar
、xxxtext或xxxBLOB
字段時,服務器將自動選擇這種表類型。相對於靜態MyISAM,這種表存儲空間比較小,但由於每條記錄的長度不一,所以多次修改數據後,數據表中的數據就可能離散的存儲在內存中,進而導致執行效率下降。同時,內存中也可能會出現很多碎片。因此,這種類型的表要經常用optimize table 命令或優化工具來進行碎片整理
。 -
壓縮MyISAM
:以上說到的兩種類型的表都可以用myisamchk工具壓縮。這種類型的表進一步減小了佔用的存儲,但是這種表壓縮之後不能再被修改。另外,因爲是壓縮數據,所以這種表在讀取的時候要先時行解壓縮。 -
優點:
有着較高的查詢和寫入速度, 獨立於操作系統, 不受 win 和linux的限制- 適用於選擇密集型的表。MyISAM存儲引擎在
篩選大量數據時非常迅速
,插入密集型的表。MyISAM的併發插入特性允許同時選擇和插入數據。
- 適用於選擇密集型的表。MyISAM存儲引擎在
-
缺點:
不支持事務
InnoDB引擎
InnoDB表類型可以看作是對MyISAM的更新產品,它提供了事務
、行級鎖機制
和外鍵約束
的功能, 而且還支持子等增加列AUTO_INCREMENT屬性.
不過, 因爲它會在主內存中建立其專用的緩衝池用於高速緩衝數據和索引, 所以InnoDB的表比MyISAM需要更多的內存和存儲.
==備註, 即便在同一個數據庫中, 也可以將多種存儲引擎混用, 如果需要支持事務, 可以選擇InnoDB, 如果該數據庫需要一個用於查詢的臨時表,可以選擇MEMORY存儲引擎 ==
索引方式
在mysql中 InnoDB和MyISAM引擎默認存儲索引的結構爲B+Tree, 並且此處B+樹索引又分爲了兩類
-
聚集索引:指索引項的排序方式和表中數據記錄排序方式一致的索引,
每張表只能有一個聚集索引
,聚集索引的葉子節點存儲了整個行數據。
一個例子
: 新華字典, 大家都用過吧, 把字典看做一張具體的數據表, 那麼字典的目錄就是聚集索引
, 並且字典中的拼音目錄是根據從a到z來進行排列的, 而且字典中每個字也是按照拼音的首部a-z進行排列的, 這就是索引項的排序方式和表中數據記錄排序方式一致。
真實場景
對於InnoDB引擎表, 通常我們會設置一個主鍵, 並且多數時候主鍵是自增的, 那此刻主鍵便是一個聚集索引
, 如果我們對一張數據表沒有明確設定主鍵的時候, 對於InnoDB引擎表又怎麼處理呢?- 首先, 如果一張表主鍵被定義了, 那麼這個主鍵就是一個聚集索引
- 其次, 如果主鍵沒有被顯示的定義, 那個該表的第一個
唯一非空索引
會作爲聚集索引 - 最後, 如果沒有主鍵, 並且
唯一索引
裏面裏面也沒有合適的, 那麼innodb內部會生成一個隱藏的主鍵作爲聚集索引,這個隱藏的主鍵是一個6個字節的列,該列的值會隨着數據的插入自增。
-
非聚集索引:非聚集索引中索引的邏輯順序與磁盤上行的物理存儲順序不同,一個表中可以擁有多個非聚集索引。葉子節點並不包含行記錄的全部數據。葉子節點除了包含鍵值以外,還存儲了一個指向改行數據的聚集索引建的書籤。
在這裏我們引入了一個詞, 唯一索引
有人可能會看不懂, 這個下面即將說到的索引類型的中的一種, 相信看完後續篇幅應該就明白了.
索引類型
爲了提高查詢的效率, 我們才使用了索引, 但是索引爲了應對不同的場景又分爲如下幾種
- 單列索引
- 普通索引
- 唯一索引
- 主鍵索引
- 組合索引
- 全文索引
- 空間索引
單列索引之普通索引
首先要明白的是, 單列索引是指, 一個索引只包含一個列, 但是一個表中可以建立多個單列索引
下面在來看普通索引, 顧名思義, 就是把在某一張數據表中的某一列作爲索引,是Mysql中最基本的索引類型, 沒有什麼限制並且允許在定義索引的列中插入重複值和空值
創建方式
- 直接創建索引
CREATE INDEX index_name ON table(column(length));
- 修改表結構方式創建索引
ALTER TABLE table_name ADD INDEX index_name ON (column(length));
- 創建表的時候創建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`column1` char(255) CHARACTER NOT NULL ,
`column2` text CHARACTER NULL ,
PRIMARY KEY (`id`),
INDEX index_name (column1(length))
)
單列索引之唯一索引
普通索引類似,不同的就是:索引列的
值必須唯一
,但允許有空值
。如果是組合索引,則列值的組合必須唯一
, 也就是類似A+B, B+C, C+D這種, 一個數據表中不能出現兩個A+B。
創建方式
- 直接創建索引
CREATE UNIQUE INDEX indexName ON table(column(length));
- 修改表結構方式創建索引
ALTER TABLE table_name ADD UNIQUE indexName ON (column(length));
- 創建表的時候創建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`column1` char(255) CHARACTER NOT NULL ,
`column2` text CHARACTER NULL ,
PRIMARY KEY (`id`),
UNIQUE indexName (column1(length))
)
單列索引之主鍵索引
可以看做是唯一索引的變種,一個表只能有
一個主鍵
,不允許有空值
。一般是在建表的時候同時創建主鍵索引
創建方式
- 直接創建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`column1` char(255) CHARACTER NOT NULL ,
`column2` text CHARACTER NULL ,
PRIMARY KEY (`id`)
)
組合索引
指多個字段上創建的索引,只有在查詢條件中使用了
創建索引時的第一個字段
,索引纔會被使用。使用組合索引時遵循最左前綴集合
解說說明最左前綴集合
一個例子
一張表中, 我們把 name
, age
, address
創建索引, 那麼索引中就按照name/age/address
的順序放置,
我們在使用的時候可以使用(name, age, address)
, 或者(name, age)
又或者(name, address)
可以看到name就被看做我們的最左前綴.
如果查詢的時候使用(age, address)
, 或者(age, name)
這樣的順序是不會根據索引進行查詢數據的.也就是稱作一種無效查詢.
創建方式
ALTER TABLE `table` ADD INDEX name_age_address ((name, age, address);
全文索引
主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較, 用在一堆文字中,通過其中的某個關鍵字等,就能找到該字段所屬的記錄行, 例如
武漢加油
, 通過武漢
,漢
, 等等關鍵字可以搜到對應的整條數據.
這種索引方式在很多非關係型的數據庫中都有體現, 例如ES, 或者MongoDB
特別注意在mysql中
全文索引只有在MyISAM引擎
纔可以使用, 並且只有char、varchar,text
列上可以創建全文索引
空間索引
空間索引是對空間數據類型的字段建立的索引,MySQL中的空間數據類型有四種,GEOMETRY、POINT、LINESTRING、POLYGON
mysql5.7及以後版本支持, 創建時候使用SPATIAL關鍵字, 並且涉及的列不能爲空.
這種索引, 筆者在目前的生產開發中, 沒有遇到過, 避免說的不完整誤導大家, 如果有需要的同學可以去參考下面一些文檔
空間索引和 ST_Geometry
MySQL5.7版本空間數據參考文檔
MySQL支持的空間數據格式
ST_Within
總結
- 爲什麼使用索引?
- 加快查詢效率
- 索引的類別有?
- 單列索引
- 普通索引
- 唯一索引
- 主鍵索引
- 組合索引
- 全文索引
- 空間索引
- 單列索引
說到了索引
, 就不得不提起視圖
, 那視圖又是怎麼回事, 移步《視圖那些事兒----基於Mysql》