SQL優化 索引

2021-10-14 12:58:21 字數 4990 閱讀 7833

索引說白了其實就是一種用於快速查詢資料的資料結構。像我在之前的工作裡mysql資料庫用的比較多一些,我了解的mysql底層索引使用的資料結構是b+tree。你像b+tree它其實就是在b-tree的基礎上優化而來的,b+tree和b-tree最大的區別就是b-tree不管是葉子節點還是非葉子節點除了儲存索引值之外還會儲存具體的資料,而b+tree只有葉子節點才會儲存具體的資料,這樣做的最大好處就是可以讓非葉子節點儲存更多的索引值,同等高度的b+tree可以維護更多的資料。樹的高度降低了,這也就意味著我們執行查詢的次數變少了,效率也就提高了。當然這個索引它也不是完美的,它也有優缺點。

優點呢就是,

第一它可以提高我們查詢資料的效率,減少對磁碟的io次數。

第二呢就是因為索引已經對資料進行過排序,所以我們在使用索引進行排序時就可以降低排序的成本,降低cpu的消耗。

缺點的話主要就兩個吧,

第一索引它會降低更新表的速度,因為在對錶進行insert、update和delete操作的時候,資料庫不僅要更新資料,還要更新索引資訊。

第二就是索引會占用額外的空間,但是我覺著有些情況下拿空間換時間還是非常值當的。所以說我們應該選擇合適的時機去建索引,不是說無論什麼情況下都去建立索引。那啥情況下去建索引呢?

s我覺著主要分三種情況吧:

第一就是頻繁作為查詢條件的字段應該建索引

第二就是跟其它表關聯的字段應該建索引

第三就是查詢中排序、統計或者分組字段應該建索引

當然還有一些情況不應該去建索引,比如說:

表記錄太少啊,

或者說你這個表或者字段經常增刪改,

再者說你where條件裡壓根用不到的字段也不要建索引。

還有就是你這個字段重複的值太多了比如說超過了50%也不太適合建索引。

當然了有時候不是說索引建立好了之後就一定會被用到,如果你寫的sql語句不好的話可能就會導致索引失效,所以我們應該在寫sql的時候注意一下以下幾點:

第乙個就是要遵守最佳左字首原則:比如說你建立了乙個復合索引index(a,b,c),那麼在寫sql語句的時候一定要從索引的第一列開始寫並且還得注意不能跳過索引中的列。

第二個就是不要索引列上做任何操作(比如說計算啊、使用函式啊、(自動or手動)型別轉換),這都會導致索引失效而轉向全表掃瞄。

第三個就是範圍條件右邊的索引會失效(比如說你範圍條件右邊與範圍條件使用的同乙個復合索引,右邊的才會失效。如果是兩個欄位走的是不同索引則不會失效)。

第四個就是咱們在寫sql的時候盡量使用覆蓋索引,覆蓋索引說白了就是只訪問索引就能夠查詢到你想要的資料,想要使用覆蓋索引具體的做法就是讓你查詢的列包含在索引列裡面,所以說我們平時寫sql的時候儘量減少select 這種寫法。

第五個就是平時寫sql的時候使用不等於(!= 或者 <>)的時候也會導致索引失效導致掃瞄全表。

第六個呢就是like以萬用字元開頭(』%abc…』)會導致索引失效變成全表掃瞄,如果一定要以萬用字元開頭可以使用咱們的覆蓋索引來解決。

第七個就是還有is not null也會導致索引失效。

大概我現在就記住了這幾個避免索引失效的方式。

你像平時我們要想知道一條sql語句在執行的時候有沒有走索引,用的最多的就是explain命令了,它可以幫我們檢視sql語句的執行計畫。這個命令返回的有幾個關鍵的列,比如說possible_keys這一列[跑shei博k死]代表的是你這次查詢可能會用到的索引,key這一列就代表你這次查詢實際用到的索引,還有乙個type列,這一列就比較重要了,它裡面顯示的值是衡量你這個查詢效能高低的重要指標。你像常見的值我記得有三個,分別是range、index還有all,range代表的意思就是只掃瞄了部分索引就查到你想要的資料,index代表掃瞄了全部索引才查到了你想要的資料,all是最差的它代表壓根沒走索引而是進行的全表掃瞄。所以說一旦我們某個查詢它的type是all就需要我們注意了。你向除了type這一列還有一列也比較重要,就是extra(埃克斯chua)這一列,它裡面主要顯示的就是一些額外的比較重要的資訊了。常見的有什麼using[有人] filesort[菲歐臊特],就說明你這次查詢使用了檔案排序。檔案排序說白了就是沒利用索引去完成排序。想解決也很簡單,我們可以給排序的字段上建立索引。有時候還會出現using[有人] temporary(太目炮rai瑞),說明你這次查詢使用了臨時表儲存中間結果,比較常見的就是分組查詢 group by。如果出現了這個也不好,這個時候咱們可以給你分組的字段上建個索引。還有些情況下會出現using index,說明你這次查詢中使用了覆蓋索引(covering index),避免了回表查詢,效率很好!

2)索引的型別

從索引的特性上來說可以分為唯一索引和普通索引。

唯一索引所在欄位中的值必須是唯一的。

主鍵欄位會自動建立唯一索引。

從字段的個數來說單值(單列、單一)索引和復合(組合)索引。

如果對多個字段同時加索引就稱之為復合索引。

3)聚集(聚合、聚簇)索引和非聚集(聚合、聚簇)索引

聚集索引的的葉子節點直接儲存的資料就是主鍵值對應的資料,可以直接獲取到主鍵值對應的全部列的值。主鍵就屬於聚集索引,而且在一張表上聚集索引只能有乙個。

而非聚集索引的葉子節點儲存的資料是只是主鍵值,如果在索引沒有覆蓋到對應的列的時候需要對聚集索引進行二次查詢。在一張表上非聚集索引可以有多個。

4)sql優化的具體做法?

這裡要強調的重點是sql優化的關鍵在於使用索引和避免索引失效。

對於大資料量的分頁不要用常規的limit開始位置,每頁條數;這樣越靠後查詢時間越長,效率越低,可以使用id>=的方法來替代,比如

select 欄位名from 表名

where id >=(select id from 表名limit 開始位置,1)

limit 每頁條數

select語句中避免使用,只查詢需要返回的字段,這樣可以減少解析sql語句的時間,以及減少頻寬,cpu,記憶體,io等各方面的消耗。

外來鍵必須加索引,這樣可以提公升多表聯查的效能。

通過冗餘字段避免多表連查,從而提高效能。比如在商品表中可以不僅有分類的id,還可以加上分類的名字,這樣就不用為了顯示分類名字而去進行多表聯查了。又比如在會員表中不僅有地區的id,還可以有地區的名字這樣也可以避免為了顯示地區名而進行多表聯查。

避免在where子句中對有索引的字段進行運算這會導致索引失效,從而進行全表掃瞄,比如select 欄位名from表名where庫存量+1>=10就需要改為select 欄位名 from表名where 庫存量》=9

在where,order by 以及gropu by 涉及的列上建立索引,為了避免全表掃瞄。

用in替代exists

主要是就是驅動順序的改變,這是效能變化的關鍵,

(1)如果是exists,那麼以外層表為驅動表,先被訪問,如果是in,那麼先執行子查詢,以內層表為驅動表。

(2)所以in適合於外表大而內錶小的情況;exists適合於外表小而內錶大的情況。

避免在where字句中對字段進行null值判斷,這樣會導致即便欄位上有索引也會進行全表掃瞄,好的處理方式就是給字段設定預設值。

通常要用小表去驅動大表,這樣可以提高效能,在left join中左邊的表為驅動表,所以應該讓左邊的表盡可能的為小表,在right join 中右邊的表為驅動表,所以應該讓右邊的表盡可能的小,在inner join 中 mysql會自動選擇較小的表為驅動表。

5)索引底層使用的資料結構?

比如說普通二叉樹、紅黑樹、hash表、b樹(b-tree)、b+樹(b+tree)等這些資料結構。我平時用mysql資料庫比較多一些,像我了解到的mysql資料庫它用的就是b+tree這種資料結構。b+tree是在b-tree的基礎上做了一些優化。b+樹只在葉子節點儲存資料,非葉子節點只儲存索引,而且相鄰葉子節點之間有乙個雙向指標。這樣在節點大小相同的情況下,b+樹能儲存更多的索引。假設乙個索引大小16b,乙個節點大小16k,則乙個節點可儲存1024個索引。而如果非葉子節點帶有儲存內容data且假設data大小為1k,則乙個節點只能儲存16個索引,變相增加了樹的高度。

6)mysql底層採用b+樹的原因

相比於普通二叉樹和紅黑樹,b+樹的乙個節點可以儲存更多的資料,因此b+樹的高度更短,因此查詢速度更快。

相比於hash表,雖然hash表對單個資料查詢更快,卻因為hash表的無序性導致範圍查詢上b+樹更勝一籌。(當然也有用hash表作為索引的資料表,但大多數仍然使用b+樹作為索引)

相對於b樹,b+樹只在葉子節點儲存資料,非葉子節點只儲存索引,而且相鄰葉子節點之間有乙個雙向指標。這樣在節點大小相同的情況下,b+樹能儲存更多的索引。假設乙個索引大小16b,乙個節點大小16k,則乙個節點可儲存1024個索引。而如果非葉子節點帶有儲存內容data且假設data大小為1k,則乙個節點只能儲存16個索引,變相增加了樹的高度。

7)那為什麼推薦使用整型自增主鍵而不是選擇uuid?

uuid是字串,比整型消耗更多的儲存空間;

在b+樹中進行查詢時需要跟經過的節點值比較大小,整型資料的比較運算比字串更快速;

自增的整型索引在磁碟中會連續儲存,在讀取一頁資料時也是連續;uuid是隨機產生的,讀取的上下兩行資料儲存是分散的,不適合執行where id > 5 && id < 20的條件查詢語句。

在插入或刪除資料時,整型自增主鍵會在葉子結點的末尾建立新的葉子節點,不會破壞左側子樹的結構;uuid主鍵很容易出現這樣的情況,b+樹為了維持自身的特性,有可能會進行結構的重構,消耗更多的時間。

8)索引的語法?

操作 命令

建立 create [unique ] index 索引名 on 表名(欄位名,…);

刪除 drop index 索引名 on 表名;

檢視 show index from 表名\g;

使用alter命令 alter table 表名 add primary key (column_list) : 該語句新增乙個主鍵,這意味著索引值必須是唯一的,且不能為 null。

alter table tbl_name add primary key (column_list)

alter table tbl_name add index index_name (column_list): 新增普通索引,索引值可出現多次。

alter table tbl_name add fulltext index_name (column_list):該語句指定了索引為 fulltext ,用於全文索引。

SQL優化 索引優化

一 發現哪些sql語句有效能問題 開啟mysql慢查詢日誌對sql語句進行監控 show variables like slow query log 檢視是否開啟慢查詢日誌 set global slow query log on 開啟慢查詢日誌 set global log queries not...

SQL優化(SQL 索引)

檢視表定義 show create table users 檢視表的索引 show index from users 你要獲取第乙個表的所有資訊,你說全表掃瞄快呢還是索引掃瞄快呢?所以當你查詢庫 包括left join中的臨時庫 的所有資訊時,資料庫會選擇最優方法 全表掃瞄!s表dept id na...

sql索引優化

1 b tree索引 b tree索引的特點 以b 樹的結構儲存資料 能加快資料的查詢速度 更適合進行範圍查詢 什麼情況下可以用到b樹索引 1 全值匹配的查詢 eg sn 1111 1111 1111 1111 2 匹配最左字首的查詢 eg sn 1111 3 匹配範圍值的查詢 eg sn sn 4...