在瞭解了索引的基礎知識及B+樹索引的原理後(如需複習請點這裏),這一節咱們瞭解一下有哪些建索引的原則,來指導咱們去建索引。html
咱們可能聽一些數據庫方面的專業人士說過:「把 Where 條件裏面的列都建上索引」,從而給每一個列給每一個列建獨立的索引,這個理解是很是錯誤的。mysql
若是 Where 條件裏有多種組合的查詢條件,能夠嘗試建聯合索引來減小索引數量,同時提高查詢性能。sql
普通索引查到主鍵後,回到主鍵索引搜索的過程,稱爲回表。數據庫
當使用普通索引查詢時,普通索引有咱們所需結果的全部信息(字段),就能夠直接提供查詢結果,而不須要回表。也就是說,在這個查詢裏,索引已經被「覆蓋了」查詢需求,稱爲覆蓋索引。性能優化
mysql> create table T ( ID int primary key, k int NOT NULL DEFAULT 0, s varchar(16) NOT NULL DEFAULT '', index k(k)) engine=InnoDB; select ID from T where k between 3 and 5
上面的例子中,k索引樹上已經包括了ID的值,就不須要回表了。性能
因爲覆蓋索引能夠減小樹的搜索次數,顯著提高查詢性能,因此使用覆蓋索引是一個經常使用的性能優化手段。優化
在使用覆蓋索引時,要注意若是須要返回的字段較多,就要權衡空間和時間。由於覆蓋索引要覆蓋較多字段就須要更多的空間。code
假設咱們有2個字段,例如身份證號和地址,如今有三種查詢需求:按身份證號查詢、按地址查詢,以及按身份證號和地址查詢。htm
若是每種須要都要建立一個索引,就顯得有利浪費。blog
從上一篇文章裏,咱們瞭解到B+樹的特色是有序的,所以咱們能夠只建立兩個索引即知足上面的三種需求,分別是(身份證號,地址)和(地址)。這就是B+樹索引的「最左前綴」原則。
在創建聯合索引的時候,如何安排索引內的字段順序:
有時候須要索引很長的字符列,這會讓索引變得大且慢。一種策略是模擬哈希索引。
一般能夠索引開始的部分字符,這樣能夠大大節約索引空間,從而提升索引效率。但這樣也會下降索引的選擇性。
索引的選擇性指,不重複的索引值(也稱爲基數,cardinality)和數據表的記錄總數(T)的比值,範圍從1/T到1之間。
假設有個訂單表,其中有包括城市名稱的字段(city,且城市名稱爲英文),下面來介紹一下如何肯定前綴索引的長度。
mysql> create table orders ( ID int primary key, city varchar(16) NOT NULL )engine=InnoDB;
一種方法是計算完整列的選擇性,並使前綴的選擇性接近於完整列的選擇性。
計算完整列的選擇性:
mysql> SELECT COUNT(DISTINCT city)/COUNT(*) FROM orders;
在同一個查詢中計算不一樣前綴長度的選擇性:
mysql> SELECT COUNT(DISTINCT LEFT(city, 3))/COUNT(*) AS sel3, COUNT(DISTINCT LEFT(city, 4))/COUNT(*) AS sel4, COUNT(DISTINCT LEFT(city, 5))/COUNT(*) AS sel5, COUNT(DISTINCT LEFT(city, 6))/COUNT(*) AS sel6, COUNT(DISTINCT LEFT(city, 7))/COUNT(*) AS sel7 FROM orders;
建立前綴索引的方法:
mysql> ALTER TABLE orders ADD KEY (city(7));
在聯合索引中,索引列的順序是按照從左到右逐列進行排序的。所以索引能夠按照升序或降序進行掃描,以知足精確符合列順序的 ORDERY BY、GROUP BY 和 DISTINCT 等子句的查詢需求。
所以聯合索引的列順序很重要。
如何選擇索引的列順序有一個經驗法則:將選擇性最高的列放到索引最前列。
這個經驗法則在某些場景下有用,但可能在另外場景下,可能就沒效了,這要根據具體狀況進行分析。