MySQL高性能索引策略和查詢性能優化


前綴索引和索引選擇性

有時候需要索引很長的字符,這會讓索引變得大且慢。一個策略是模擬哈希索引

通常可以索引開始的部分字符,這樣可以大大解約索引空間,提高索引效率。但這樣會降低索引的選擇性。

索引的選擇性:不重復的索引值(也成為基數)和數據表的記錄總數比值。索引的選擇性越高則查詢效率越高,因為選擇性高的索引可以在查找時過濾更多的行。唯一索引的選擇性為1,是選擇性最好的。

前綴索引是一種能使索引更小更快的辦法,但也有缺點:

MySQL無法使用ORDER BY和GROUP BY,也無法使用覆蓋掃描。

聚簇索引

聚簇索引並不是一種單獨的索引類型,是一種數據存儲方式。

當表有聚簇索引時,它的數據行實際上存放在索引的葉子頁。

聚簇:數據行和相鄰的鍵值緊湊的存儲在一起。

如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替。

如果沒有這樣的索引,會隱式定義一個主鍵作為聚簇索引。

聚簇索引的缺點

  • 插入速度嚴重依賴插入順序。按照主鍵的順序插入是加載數據到InnoDB表中速度最快的方式。但如果不是按照主鍵順序加載數據,最好使用OPYIMIZE TABLE重新組織表。

  • 基於聚簇索引的表在插入新行,或者主鍵被遷移時,可能會“頁分裂”。當行的主鍵值要求必須將這一行插入到某個已滿的頁中時,存儲引擎會將該頁分裂成兩個頁面來容納該行,這是一次頁分裂操作。頁分裂會導致表占用更多的磁盤空間。

覆蓋索引

通常大家會根據查詢的WHERE條件創建合適的索引,設計優秀的索引也可以使用索引來直接獲取列的數據。

如果索引的葉子結點已經包含要查詢的數據,那還要什么必要再回表查詢呢?如果一個索引包含所有需要查詢的字段的值,我們稱之為“覆蓋索引”。
image

延遲關聯

使用inner join做子查詢。在查詢的第一個階段可以使用覆蓋索引。雖然無法使用索引覆蓋整個查詢,但比完全無法利用索引覆蓋的好。

冗余和重復索引

索引越大越多,插入數據越慢。

可以使用Percona Toolkit中的pt-duplicate-key-checker分析表結構找出冗余的索引。

單表建多少個索引才合適?

  • 大表,主鍵有一個唯一索引。再有一到兩個組合索引,最多三個索引足夠用了。

  • 索引數量不能超過4個/表。

  • 一切服從應用需要。在一張表上創建多少索引,創建什么樣的索引,並無一定之規。不能說一張表上有了 7個索引,就不能再創建第 8個索引了。

  • 索引的多少取決於具體的業務場景。

  • 在oltp中,表經常需要insert等,那么索引不能過多,一般超過3個就會對性能有影響。

  • 在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過濾條件

查詢性能優化

對於性能低下的查詢,通過兩個步驟來分析非常有效:

1、確認應用程序是否在檢索大量超過需要的數據。這意味着訪問了過多的行或者是過多的列。

2、確認MySQL服務器層是否在分析大量超過需要的數據行。

  • 比如使用 * 來返回全部列,其實有些列是用不到的,應該精簡,或者說重復查詢相同改的數據,這應該把這種數據放到緩存里,下次查先從緩存取,熱點數據每次取可以給加過期時間。

  • 確認EXPLAIN中掃描的行數和訪問類型
    在EXPLAIN中的type列是訪問類型,從全表掃描、索引掃描、范圍掃描、唯一索引查詢、常數引用(全索范唯),他們的查詢速度是從慢到快。

Re

《高性能MySQL》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM