1. 程式人生 > 資料庫 >90%程式設計師面試會遇到的索引優化問題

90%程式設計師面試會遇到的索引優化問題

前言

本文給大家分享了90%程式設計師面試都用得上的索引優化,重點提一下,索引基本原理和建立索引的原則是重點,面試基本必問!大家可以收藏好多理解理解。下面來一起看看詳細的介紹吧。

關於索引,分為以下幾點來講解(技術文):

  • 索引的概述(什麼是索引,索引的優缺點)
  • 索引的基本使用(建立索引)
  • 索引的基本原理(面試重點)
  • 索引的資料結構(B樹,hash)
  • 建立索引的原則(重中之重,面試必問!敬請收藏!)
  • 百萬級別或以上的資料如何刪除

一、索引的概述

1)什麼是索引?

索引是一種特殊的檔案(InnoDB資料表上的索引是表空間的一個組成部分),它們包含著對資料表裡所有記錄的引用指標。更通俗的說,索引就相當於目錄。當你在用新華字典時,幫你把目錄撕掉了,你查詢某個字開頭的成語只能從第一頁翻到第一千頁。累!把目錄還給你,則能快速定位!

2)索引的優缺點:

可以大大加快資料的檢索速度,這也是建立索引的最主要的原因。,且通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的效能。但是,索引也是有缺點的:索引需要額外的維護成本;因為索引檔案是單獨存在的檔案,對資料的增加,修改,刪除,都會產生額外的對索引檔案的操作,這些操作需要消耗額外的IO,會降低增/改/刪的執行效率。

二、索引的基本使用(真技術文)

1)建立索引:(三種方式)

第一種方式:


第二種方式:使用ALTER TABLE命令去增加索引:

ALTER TABLE用來建立普通索引、UNIQUE索引或PRIMARY KEY索引。


其中table_name是要增加索引的表名,column_list指出對哪些列進行索引,多列時各列之間用逗號分隔。

索引名index_name可自己命名,預設時,MySQL將根據第一個索引列賦一個名稱。另外,ALTER TABLE允許在單個語句中更改多個表,因此可以在同時建立多個索引。

第三種方式:使用CREATE INDEX命令建立

CREATE INDEX可對錶增加普通索引或UNIQUE索引。(但是,不能建立PRIMARY KEY索引)


三、索引的基本原理(不想像別的文章那樣一大堆篇幅廢話)

索引用來快速地尋找那些具有特定值的記錄。如果沒有索引,一般來說執行查詢時遍歷整張表。

索引的原理很簡單,就是把無序的資料變成有序的查詢

1、把建立了索引的列的內容進行排序

2、對排序結果生成倒排表

3、在倒排表內容上拼上資料地址鏈

4、在查詢的時候,先拿到倒排表內容,再取出資料地址鏈,從而拿到具體資料

四、索引的資料結構(b樹,hash)

1)B樹索引

mysql通過儲存引擎取資料,基本上90%的人用的就是InnoDB了,按照實現方式分,InnoDB的索引型別目前只有兩種:BTREE(B樹)索引和HASH索引。B樹索引是Mysql資料庫中使用最頻繁的索引型別,基本所有儲存引擎都支援BTree索引。通常我們說的索引不出意外指的就是(B樹)索引(實際是用B+樹實現的,因為在查看錶索引時,mysql一律列印BTREE,所以簡稱為B樹索引)


查詢方式:

主鍵索引區:PI(關聯儲存的時資料的地址)按主鍵查詢,

普通索引區:si(關聯的id的地址,然後再到達上面的地址)。所以按主鍵查詢,速度最快

B+tree性質:

1.)n棵子tree的節點包含n個關鍵字,不用來儲存資料而是儲存資料的索引。

2.)所有的葉子結點中包含了全部關鍵字的資訊,及指向含這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大順序連結。

3.)所有的非終端結點可以看成是索引部分,結點中僅含其子樹中的最大(或最小)關鍵字。

4.)B+ 樹中,資料物件的插入和刪除僅在葉節點上進行。

5.)B+樹有2個頭指標,一個是樹的根節點,一個是最小關鍵碼的葉節點。

2)雜湊索引(好技術文)

簡要說下,類似於資料結構中簡單實現的HASH表(散列表)一樣,當我們在mysql中用雜湊索引時,主要就是通過Hash演算法(常見的Hash演算法有直接定址法、平方取中法、摺疊法、除數取餘法、隨機數法),將資料庫欄位資料轉換成定長的Hash值,與這條資料的行指標一併存入Hash表的對應位置;如果發生Hash碰撞(兩個不同關鍵字的Hash值相同),則在對應Hash鍵下以連結串列形式儲存。當然這只是簡略模擬圖。


ps:關於資料結構,有興趣深入的朋友可以關注我後檢視【資料結構】專題,這裡不做詳細講解。

五、建立索引的原則(重中之重)

索引雖好,但也不是無限制的使用,最好符合一下幾個原則

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

2)較頻繁作為查詢條件的欄位才去建立索引

3)更新頻繁欄位不適合建立索引

4)若是不能有效區分資料的列不適合做索引列(如性別,男女未知,最多也就三種,區分度實在太低)

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

6)定義有外來鍵的資料列一定要建立索引。

7)對於那些查詢中很少涉及的列,重複值比較多的列不要建立索引。

8)對於定義為text、image和bit的資料型別的列不要建立索引。

百萬級別或以上的資料如何刪除(真好技術文)

關於索引:由於索引需要額外的維護成本,因為索引檔案是單獨存在的檔案,所以當我們對資料的增加,會降低增/改/刪的執行效率。所以,在我們刪除資料庫百萬級別資料的時候,查詢MySQL官方手冊得知刪除資料的速度和建立的索引數量是成正比的。

  • 所以我們想要刪除百萬資料的時候可以先刪除索引(此時大概耗時三分多鐘)
  • 然後刪除其中無用資料(此過程需要不到兩分鐘)
  • 刪除完成後重新建立索引(此時資料較少了)建立索引也非常快,約十分鐘左右。
  • 與之前的直接刪除絕對是要快速很多,更別說萬一刪除中斷,一切刪除會回滾。那更是坑了。

常用的資料庫索引優化語句

使用如下的表tb_test作為示例進行說明:

create table tb_test
(
id int not null,age int not null,name varchar(30) not null,addr varchar(50) not null
);
create unique index idx1_tb_test on tb_test(id);
create index idx2_tb_test on tb_test(name);
create index idx3_tb_test on tb_test(addr);

索引優化建議

1.對索引列進行計算

例如,我們想要將表tb_test中id大於100的資料記錄中的age和name查找出來。

正確的SQL語句是:

select age,name from tb_test where id > 1*100;

不建議採用的SQL語句是:

select age,name from tb_test where id/100 > 1;

2.對索引列進行拼接

例如,我們想要將表tb_test中name為“zhou”、addr為“CQ”的記錄中的id和age查找出來。

正確的SQL語句是:

select id,age from tb_test where name='zhou' and addr='CQ';

不建議採用的SQL語句是:

select id,age from tb_test where concat(name,' ‘,addr) = ‘zhou CQ';

3.在索引列上is null或is not null的使用

例如,我們想要將表tb_test中id大於等於“0”的記錄中的age查找出來。

正確的SQL語句是:

select age from tb_test where id >= 0;

不建議採用的SQL語句是:

select age from tb_test where id is not null;

4.在索引列上or的使用

例如,我們想要將表tb_test中id等於101或102的記錄中的age和name查找出來。

正確的SQL語句(使用union)是:

select age,name from tb_test where id = 101 union select age,name from tb_test where id = 102;

不建議採用的SQL語句(使用or)是:

select age,name from tb_test where id = 101 or id = 102;

5.儘可能避免索引列在like的首字元使用萬用字元

例如,我們想要將表tb_test中name匹配“zho”的記錄中的id和age查找出來。

正確的SQL語句是:

select id,age from tb_test where name like ‘zho%';

不建議採用的SQL語句是:

select id,age from tb_test where name like ‘%ho%';

6.複合索引的使用

如果我們建立的索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引。

例如,我們在表tb_test上新建瞭如下索引:

create index idx4_tb_test on tb_test(id,name,addr);

以上索引idx4_tb_test相當於建立了index(id)、index(id,name)、index(id,addr) 這3個索引。在SQL語句的where條件中單獨使用name或addr時不會使用到該索引,必須使用id時才會使用到該索引。

在我們編寫的SQL語句中,不正確地使用索引列可能會導致索引不被使用,而進行全表掃描,極大地降低了資料庫的效能。因此,學習正確的索引的使用方法實在是很有必要的。

今天,索引的講解就到這裡,重點提一下,索引基本原理和建立索引的原則是重點,面試基本必問!大家可以收藏好多理解理解。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。