1. 程式人生 > 實用技巧 >面試題目整理(MySQL系列-索引)

面試題目整理(MySQL系列-索引)

最近又開始面試了,整理一些面試的高頻考點吧。有幸參與一次社招面試,看的還是底層知識:

1、資料庫儲存引擎分類:

  (1):儲存引擎主要有: 1. MyISAM(不支援事務) , 2. InnoDB(支援事務、行級鎖定和外來鍵), 3. Memory, 4. Archive, 5. Federated 。 預設為:InnoDB 引擎。InnoDB 底層儲存結構為 B+樹, B 樹的每個節點對應 innodb 的一個 page,page 大小是固定的,一般設為 16k

  (2):使用場景?

       1)經常更新的表,適合處理多重併發的更新請求。

       2)支援事務。

       3)可以從災難中恢復(通過 bin-log 日誌等)。

       4)外來鍵約束。只有他支援外來鍵。

      5)支援自動增加列屬性 auto_increment。

2、建立索引的原則:

(1) :選擇唯一性索引:唯一性索引的值是唯一的。可以更快的通過該索引來確定某條記錄。
(2) :為經常需要排序、分組、以及聯合查詢的列建立索引。
(3) :為經常作為查詢條件的列建立索引。
(4) :限制索引的數目:越多的索引越導致表的查詢效率變低,因為索引表在每次更新表資料的時候都會重新建立這個表的索引,表的資料越多,索引列越多,那麼建立索引的時間消耗就越大。
(5) :如果索引的值很長,那麼查詢的速度會受到影響。
(6) :如果索引欄位的值很長,最好使用值得字首來進行索引。
(7) :刪除不再使用或者很少使用的索引。
(8) :最左字首匹配原則,非常重要的原則。
(9) :儘量選擇區分度高的列作為索引.
(10): 索引列不能參與計算,保持列“乾淨”:帶函式的查詢不參與索引。
(11):儘量的擴充套件索引,不要新建索引。

3、使用索引的一些注意點:

(1):like以%開頭索引無效,當like以&結尾,索引有效。
(2):當且僅當or語句查詢條件的前後列均為索引時,索引生效。
(3):組合索引,使用的不是第一列索引時候,索引失效,即最左匹配規則。
(4):資料型別出現隱式轉換,如varchar不加單引號的時候可能會自動轉換為int型別,這個時候索引失效。
(5):在索引列上使用IS NULL或者 IS NOT NULL 時候,索引失效,因為索引是不索引空值得。
(6):在索引欄位上使用,NOT、 <>、!= 、時候是不會使用索引的,對於這樣的處理只會進行全表掃描。
(7):對索引欄位進行計算操作,函式操作時不會使用索引。
(8):當全表掃描速度比索引速度快的時候不會使用索引。

4、索引分類

(1):單列索引
	1)普通索引:MySQL中基本索引型別,沒有什麼限制,允許在定義索引的列中插入重複值和空值,純粹為了查詢資料更快一點。
	2)唯一索引:索引列中的值必須是唯一的,但是允許為空值,
	3)主鍵索引:是一種特殊的唯一索引,不允許有空值。
(2):組合索引:多個欄位組合上建立的索引,只有在查詢條件中使用了這些欄位的左邊欄位時,索引才會被使用,使用組合索引時遵循最左字首集合。
(3):全文索引:只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT	型別欄位上使用全文索引,介紹了要求,說說什麼是全文索引,就是在一堆文字中,通過其中的某個關鍵字等,就能找到該欄位所屬的記錄行,比如有"你是個靚仔,靚女 ..."   通過靚仔,可能就可以找到該條記錄
(4):空間索引:空間索引是對空間資料型別的欄位建立的索引,MySQL中的空間資料型別有四種,GEOMETRY、POINT、LINESTRING、POLYGON。在建立空間索引時,使用SPATIAL關鍵字。要求,引擎為MyISAM,建立空間索引的列,必須將其宣告為NOT NULL。

5、新增索引

主鍵索引:ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
唯一索引:ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 
普通索引:ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 
全文索引:ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 
多列索引:ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

6、B+樹索引和Hash索引的區別

1:hash索引適合等值查詢,但是無法進行範圍查詢,B+樹索引支援範圍查詢
2:hash索引沒辦法利用索引完成排序。
3:hash索引不支援多列聯合索引的最左匹配規則。
4:如果有大量重複健值得情況下,hash索引的效率會很低,因為雜湊碰撞問題。

7、聚簇索引和非聚簇索引

innoDB的B+Tree儲存了整行資料的是主鍵索引,也被成為聚湊索引。
儲存主鍵的值:成為非主鍵索引,也被稱為非聚湊索引
優劣:
    聚簇索引查詢會更加快些。因為主鍵索引樹的頁子節點儲存的是整行資料。
    也就是我們需要得到的資料。而非主鍵索引的頁子節點是主鍵的值,
    查詢的主鍵之後,我們還需要通過主鍵的值再次進行查詢資料。(這個過程被稱之為回表)。

8、最左匹配原則

  在建立聯合索引時候,一般需要遵循最左匹配原則。即聯合索引中的屬性識別度最高的放在查詢語句的最前面。

9、優化器的執行

1:根據搜尋條件,找出可能使用的索引。
2:計算全表掃描的代價。
3:計算使用不同索引執行查詢的代價。
4:對比各種執行方案的代價,找出成本最低的一個。

10、MySQL5.6和MySQL5.7對於索引的優化

mysql5.6引入了索引下推優化,預設是開啟的。
    例子:user表中(a,b,c)構成一個索引。
        select * from user where a='23' and b like '%eqw%' and c like 'dasd'。
    解釋:如果沒有索引下推原則,則mysql會通過a='23' 先查詢出一個對應的資料。然後返回到mysql服務端。
        mysql服務端再基於兩個like模糊查詢來校驗and查詢出的資料是否符合條件。這個過程就設計到回表操作。
    
    如果使用了索引下推技術,則mysql會首先返回返回條件a='23'的資料的索引,然後根據模糊查詢的條件來校驗索引行資料是否符合條件,
   如果符合條件,則直接根據索引來定位對應的資料,如果不符合直接reject掉。因此,有了索引下推優化,可以在有like條件的情況下,減少回表的次數。

11、InnoDB和MyISAM的區別

(1)InnoDB 支援事務,MyISAM 不支援事務。這是 MySQL 將預設儲存引擎從 MyISAM 變成 InnoDB 的重要原因之一;
(2)InnoDB 支援外來鍵,而 MyISAM 不支援。對一個包含外來鍵的 InnoDB 錶轉為 MYISAM 會失敗;
(3)InnoDB 是聚簇索引,MyISAM 是非聚簇索引。
       聚簇索引的檔案存放在主鍵索引的葉子節點上,因此 InnoDB 必須要有主鍵,
       通過主鍵索引效率很高。但是輔助索引需要兩次查詢,先查詢到主鍵,然後再
       通過主鍵查詢到資料。因此,主鍵不應該過大,因為主鍵太大,其他索引也都會很大。
       而 MyISAM 是非聚集索引,資料檔案是分離的,索引儲存的是資料檔案的指標。
       主鍵索引和輔助索引是獨立的。
(4)InnoDB 不儲存表的具體行數,
        執行select count(*) from table 時需要全表掃描。
        而 MyISAM 用一個變數儲存了整個表的行數,執行
        上述語句時只需要讀出該變數即可,速度很快;
(5)InnoDB 最小的鎖粒度是行鎖,MyISAM 最小的鎖粒度是表鎖。
       一個更新語句會鎖住整張表,導致其他查詢和更新都會被阻塞,
        因此併發訪問受限。這也是 MySQL 將預設儲存引擎從 MyISAM 變成 InnoDB 的重要原因之一;
    

  稀奇古怪的面試題:

一張表,裡面有ID自增主鍵,當insert了17條記錄之後,刪除了第15,16,17條記錄,再把Mysql重啟,再insert一條記錄,這條記錄的ID是18還是15 ?

   如果表的型別是MyISAM,那麼是18。因為MyISAM表會把自增主鍵的最大ID 記錄到資料檔案中,重啟MySQL自增主鍵的最大ID也不會丟失;
   如果表的型別是InnoDB,那麼是15。因為InnoDB 表只是把自增主鍵的最大ID記錄到記憶體中,所以重啟資料庫或對錶進行OPTION操作,都會導致最大ID丟失。

哪個儲存引擎執行 select count(*) 更快,為什麼?

    MyISAM更快,因為MyISAM內部維護了一個計數器,可以直接調取。

    在 MyISAM 儲存引擎中,把表的總行數儲存在磁碟上,當執行 select count(*) from t 時,直接返回總資料。

    在 InnoDB 儲存引擎中,跟 MyISAM 不一樣,沒有將總行數儲存在磁碟上,當執行 select count(*) from t 時,會先把資料讀出來,一行一行的累加,最後返回總數量。

    InnoDB 中 count(*) 語句是在執行的時候,全表掃描統計總數量,所以當資料越來越大時,語句就越來越耗時了,為什麼 InnoDB 引擎不像 MyISAM 引擎一樣,將總行數儲存到磁碟上?這跟 InnoDB 的事務特性有關,由於多版本併發控制(MVCC)的原因,InnoDB 表“應該返回多少行”也是不確定的。

12、索引本身也很大,不可能全部儲存在記憶體中,一般以索引檔案的形式儲存在磁碟上,存貯形式: