索引使用的基本原則

  咱們在建表的時候最好建立自增主鍵,這樣非主鍵索引佔用的空間就比較小。這種方式插入數據都是追加數據,不涉及到數據頁分裂。但也不是全部場景下都須要自增主鍵,好比有些業務場景的需求是只有一個索引而且該索引必須是惟一索引,因爲沒有其餘索引,就不用考慮輔助索引的存儲空間消耗,能夠直接將這個索引設爲主鍵。sql

覆蓋索引數據庫

  好比ID、k是表T中的主鍵索引和輔助索引,如今有一條查詢需求:性能優化

select ID from T where k between 3 and 5;

  由於k索引樹中葉子結點值存放的就是ID值,能夠直接查詢到結果,這時就不須要再回表。若是查詢的結果是聯合索引的字段,一樣不須要回表操做。索引k覆蓋了咱們的查詢需求,這種索引就叫覆蓋索引。因爲覆蓋索引能夠減小搜索索引樹的次數,所以這是一個經常使用的數據庫性能優化方法。 性能

聯合索引優化

  簡要的說就是由多個字段組成的索引,假設如今有張市民信息表T:spa

CREATE TABLE `tuser` (
  `id` int(11) NOT NULL,
  `id_card` varchar(32) DEFAULT NULL,
  `name` varchar(32) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `ismale` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `id_card` (`id_card`),
  KEY `name_age` (`name`,`age`)
) ENGINE=I

  裏面有身份證號 id_card、姓名 name等字段,有個高頻請求:根據身份證號查詢姓名,那麼咱們就能夠建立 (id_card, name) 聯合索引,這裏會用到覆蓋索引,再也不須要回表查詢整行記錄。索引的維護是有代價的,怎樣創建聯合索引須要考慮具體的業務場景。code

最左前綴原則blog

  有時候咱們會遇到不常見的查詢請求,好比根據身份證號查詢市民的家庭住址。若是咱們走全表掃描效率過低,單首創建一個索引又浪費空間,這會就能夠用B+樹索引的最左前綴原則。用聯合索引 (name, age) 來講明這個概念:索引

        

  好比需求是查詢全部名字是張三的人,能夠快速定位到 ID4,而後向後掃描全部知足條件的數據。若是查詢姓張的人,sql裏條件部分能夠這樣寫 「 where name like '張%' 」,一樣也能用到上面的聯合索引。這裏最左前綴能夠是聯合索引的最左N個字段,也能夠是字符串索引的最左M個字符。資源

  那咱們該如何創建聯合索引呢?首先要遵循一個原則:若是經過調整索引順序,能夠少維護一個索引,那麼這個順序就是優先考慮的。好比上面的(id_card,name)索引,根據 id_card 查詢家庭住址就不要再創建 聯合索引了。

若是既有聯合查詢,又有基於a、b各自的查詢,好比查詢語句中只有索引b是不能用聯合索引 (a,b)的。那麼就要創建兩個索引,考慮的原則是索引佔用空間。好比市民信息表中 name 字段比 age 佔用空間大,就建立一個 (name, age)聯合索引和一個 (age)的單字段索引。

  對於聯合索引,還有一個問題:字段中不符合最左前綴的部分會怎麼樣?一樣用上面的 (name, age) 索引來講明,如今有一個需求:「查詢出名字第一個字是張,年齡爲10歲的男孩」。sql是這樣的:

select * from T where name like '張%' and age = 10 and ismale = 1;

在MySQL5.6以前,只能不停的回表查到最後的結果;5.6以後引入了索引下推優化,就是在索引遍歷過程當中,對索引中包含的字段中先作判斷,過濾掉不知足條件的記錄,減小回表的次數。用兩個圖來解釋:分別是優化先後

能夠看到原來是4次回表,優化後變成2次,減小了對資源的訪問。

相關文章
相關標籤/搜索