前綴索引和索引選擇性
有時候需要索引很長的字符,這會讓索引變得大且慢,一個策略是前面提到的模擬哈希索引,
通常可以索引開始的部分字符,這樣可以大大解約索引空間,提高索引效率,但這樣會降低索引的選擇性,
索引的選擇性:不重復的索引值(也成為基數)和資料表的記錄總數比值,索引的選擇性越高則查詢效率越高,因為選擇性高的索引可以在查找時過濾更多的行,唯一索引的選擇性為1,是選擇性最好的,
前綴索引是一種能使索引更小更快的辦法,但也有缺點:
MySQL無法使用ORDER BY和GROUP BY,也無法使用覆寫掃描,
聚簇索引
聚簇索引并不是一種單獨的索引型別,是一種資料存盤方式,
當表有聚簇索引時,它的資料行實際上存放在索引的葉子頁,
聚簇:資料行和相鄰的鍵值緊湊的存盤在一起,
如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替,
如果沒有這樣的索引,會隱式定義一個主鍵作為聚簇索引,
聚簇索引的缺點
-
插入速度嚴重依賴插入順序,按照主鍵的順序插入是加載資料到InnoDB表中速度最快的方式,但如果不是按照主鍵順序加載資料,最好使用OPYIMIZE TABLE重新組織表,
-
基于聚簇索引的表在插入新行,或者主鍵被遷移時,可能會“頁分裂”,當行的主鍵值要求必須將這一行插入到某個已滿的頁中時,存盤引擎會將該頁分裂成兩個頁面來容納該行,這是一次頁分裂操作,頁分裂會導致表占用更多的磁盤空間,
覆寫索引
通常大家會根據查詢的WHERE條件創建合適的索引,設計優秀的索引也可以使用索引來直接獲取列的資料,
如果索引的葉子結點已經包含要查詢的資料,那還要什么必要再回表查詢呢?如果一個索引包含所有需要查詢的欄位的值,我們稱之為“覆寫索引”,
延遲關聯
使用inner join做子查詢,在查詢的第一個階段可以使用覆寫索引,雖然無法使用索引覆寫整個查詢,但比完全無法利用索引覆寫的好,
冗余和重復索引
索引越大越多,插入資料越慢,
可以使用Percona Toolkit中的pt-duplicate-key-checker分析表結構找出冗余的索引,
單表建多少個索引才合適?
大表,主鍵有一個唯一索引,再有一到兩個組合索引,最多三個索引足夠用了,
索引數量不能超過4個/表,
一切服從應用需要,在一張表上創建多少索引,創建什么樣的索引,并無一定之規,不能說一張表上有了 7個索引,就不能再創建第 8個索引了,
索引的多少取決于具體的業務場景,
比如在oltp中,表經常需要insert等,那么索引不能過多,一般超過3個就會對性能有影響,
在olap中如果表只是用于查詢,那么建多個索引也無妨,
但olap在資料加載的時候需要手動將索引失效,等資料加載完畢在重新建索引,這樣能提高加載的速度,
索引和鎖
索引可以讓查詢鎖定更少的行,但是,如果索引無法過濾掉無效的行,那么在InnoDB檢索到資料并回傳給服務器層以后,MySQL才能用那個用WHERE子句,這時已經無法避免鎖定行了:InnoDB已經鎖定了這些行,
mysql> select actor_id from sakila.actor where actor_id < 5 and actor_id <> 1 for update;
雖然這條查詢回傳的是2,3,4,但是實際上獲取了1-4的排他鎖,
話句話說,存盤引擎的操作是“找小于5的記錄”,服務器并沒有告訴InnoDB可以過濾第1行的WHERE條件,注意到EXPLAIN的Extra列出現了“Using where”,這表示MySQL將存盤引擎回傳行以后再應用WHERE過濾條件,
using where 代表MYSQL服務器層在存盤引擎層回傳行以后再應用WHERE過濾條件
Re
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/304558.html
標籤:其他
