關於Mysql索引的優化以及原理學習

2022-06-30 20:33:08 字數 3782 閱讀 7362

1.最左字首匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

2.=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式。

3.盡量選擇區分度高的列作為索引,區分度的公式是count(distinct col)/count(*),表示欄位不重複的比例,比例越大我們掃瞄的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大資料面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃瞄10條記錄。

4.索引列不能參與計算,保持列「乾淨」,比如from_unixtime(create_time) = 』2014-05-29』就不能使用到索引,原因很簡單,b+樹中存的都是資料表中的字段值,但進行檢索時,需要把所有元素都應用函式才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(』2014-05-29』)。

5.盡量的擴充套件索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可。

1.模糊查詢不能使用索引

2.union、in、or 都能夠命中索引 (優化 cpu耗費 union < in < or)

3.負向條件查詢不能使用索引,可以優化為 in 查詢 (負向條件有:!=、<>、not in、not exists、not like 等)

4.聯合索引最左字首原則(又叫最左側查詢) (如果在(a,b,c)三個欄位上建立聯合索引,那麼它能夠加快 a | (a,b) | (a,b,c) 三組查詢速度。)

建聯合索引的時候,區分度最高的字段在最左邊。

如果建立了(a,b)聯合索引,就不必再單獨建立 a 索引。同理,如果建立了(a,b,c)聯合索引,就不必再單獨建立 a、(a,b) 索引。

存在非等號和等號混合判斷條件時,在建索引時,請把等號條件的列前置。如 where a>? and b=?,那麼即使 a 的區分度更高,也必須把 b 放在索引的最前列。

最左側查詢需求,並不是指 sql 語句的 where 順序要和聯合索引一致。

5.範圍列可以用到索引(聯合索引必須是最左字首)。

範圍條件有:<、<=、>、>=、between等。

範圍列可以用到索引(聯合索引必須是最左字首),但是範圍列後面的列無法用到索引,索引最多用於乙個範圍列,如果查詢條件中有兩個範圍列則無法全用到索引。

6.把計算放到業務層而不是資料庫層。

select * fromdoc where year(create_time) <= '2016'

即使 date 上建立了索引,也會全表掃瞄,可優化為值計算,如下:

select * fromdoc where create_time <= '2016-01-01'

7.強制型別轉換會全表掃瞄

如果 phone 欄位是 varchar 型別,則下面的 sql 不能命中索引。

select * fromuser where phone=13800001234

可以優化為:

select * fromuser where phone='13800001234'

8.更新十分頻繁、資料區分度不高的字段上不宜建立索引。

更新會變更 b+ 樹,更新頻繁的字段建立索引會大大降低資料庫效能。

「性別」這種區分度不大的屬性,建立索引是沒有什麼意義的,不能有效過濾資料,效能與全表掃瞄類似。

一般區分度在80%以上的時候就可以建立索引,區分度可以使用 count(distinct(列名))/count(*) 來計算。

9.如果有 order by、group by 的場景,請注意利用索引的有序性。

order by 最後的字段是組合索引的一部分,並且放在索引組合順序的最後,避免出現 file_sort 的情況,影響查詢效能。

例如對於語句 where a=? and b=? order by c,可以建立聯合索引(a,b,c)。

如果索引中有範圍查詢,那麼索引有序性無法利用,如 where a>10 order by b;,索引(a,b)無法排序。

10.使用短索引(又叫字首索引)來優化索引。

字首索引,就是用列的字首代替整個列作為索引 key,當字首長度合適時,可以做到既使得字首索引的區分度接近全列索引,同時因為索引 key 變短而減少了索引檔案的大小和維護開銷,可以使用 count(distinct left(列名, 索引長度))/count(*) 來計算字首索引的區分度。

字首索引兼顧索引大小和查詢速度,但是其缺點是不能用於 order by 和 group by 操作,也不能用於覆蓋索引(covering index,即當索引本身包含查詢所需全部資料時,不再訪問資料檔案本身),很多時候沒必要對全欄位建立索引,根據實際文字區分度決定索引長度即可。

例如對於下面的 sql 語句:

selec *from employees.employees where first_name='eric'and last_name='anido';

我們可以建立索引:(firstname, lastname(4))。

11.建立索引的列,不允許為 null。

單列索引不存 null 值,復合索引不存全為 null 的值,如果列允許為 null,可能會得到「不符合預期」的結果集,所以,請使用 not null 約束以及預設值。

12.利用延遲關聯或者子查詢優化超多分頁場景。

mysql 並不是跳過 offset 行,而是取 offset+n 行,然後返回放棄前 offset 行,返回 n 行,那當 offset 特別大的時候,效率就非常的低下,要麼控制返回的總頁數,要麼對超過特定閾值的頁數進行 sql 改寫。

示例如下,先快速定位需要獲取的 id 段,然後再關聯:

selecta.* from 表1 a,(select id from 表1 where 條件 limit100000,20 ) b where a.id=b.id

13.業務上具有唯一特性的字段,即使是多個欄位的組合,也必須建成唯一索引。

不要以為唯一索引影響了 insert 速度,這個速度損耗可以忽略,但提高查詢速度是明顯的。另外,即使在應用層做了非常完善的校驗控制,只要沒有唯一索引,根據墨菲定律,必然有髒資料產生。

14.超過三個表最好不要 join。

需要 join 的字段,資料型別必須一致,多表關聯查詢時,保證被關聯的字段需要有索引。

15.如果明確知道只有一條結果返回,limit 1 能夠提高效率。

16.sql 效能優化 explain 中的 type:至少要達到 range 級別,要求是 ref 級別,如果可以是 consts 最好。

consts:單錶中最多只有乙個匹配行(主鍵或者唯一索引),在優化階段即可讀取到資料。

ref:使用普通的索引(normal index)。

range:對索引進行範圍檢索。

當 type=index 時,索引物理檔案全掃,速度非常慢。

17.單錶索引建議控制在5個以內。

18.單索引欄位數不允許超過5個。字段超過5個時,實際已經起不到有效過濾資料的作用了。

19.建立索引時避免以下錯誤觀念

索引越多越好,認為乙個查詢就需要建乙個索引。

寧缺勿濫,認為索引會消耗空間、嚴重拖慢更新和新增速度。

抵制惟一索引,認為業務的惟一性一律需要在應用層通過「先查後插」方式解決。

過早優化,在不了解系統的情況下就開始優化。

Mysql優化以及索引優化

普通索引 無限制 允許空和重複 純粹為查詢更快 唯一索引 可為空 但空只能為乙個 主鍵索引 不允許為空 組合索引 多列 最左字首原則 如 組合索引列 a b c 則查詢sql中 where a 可以使用索引 where b 不可使用 全文索引 空間索引 非聚簇索引 非聚集索引 索引樹的葉子節點存資料...

關於MySql的索引原理以及優化原則

在面試或者實際的工作中,我們都會遇到會需要優化mysql的場景,那麼優化mysql的原理到底是什麼呢。根據當前的我們可以根據他的執行過程來進行對應的優化操作。1.避免使用select 或者盡量使用limit 1這種限量級的語句 原因 從上圖我們可以看到,mysql是的通訊協議是 半雙工 的,意思就是...

MySql語句優化以及索引介紹

innodb和myisam 主要是這兩個其他可以忽略 兩者的特點和區別 innodb myisam msyql中的事務隔離級別 首先理解髒讀 不可重複讀和幻讀的含義。髒讀 讀到乙個事務未提交的資料。不可重複讀 事務1讀取了一行資料,但是事務未結束時,事務2對該資料進行修改了,事務1再次讀取時,兩次讀...