目錄
2.3 MySQL中的常用的存儲引擎 MyISAM與InnoDB的區別?
2.5 MyISAM與InnoDB實現BTree索引的方式不同在哪?
2.8 既然索引這麼多好處,爲什麼不給表中的每一列都創建索引?(索引的缺點?)
2.9 使用索引有哪些注意事項?(使用索引時,SQL語句怎麼優化?)
一、索引介紹以及使用
1.1 什麼是索引?
MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。
從官方定義中,我們可以知道索引本質是一種數據結構。
詳細一點的解釋就是:
數據庫除了數據本身之外,數據庫還維護着一個滿足特定查找算法的數據結構,這些數據結構通過某種方式指向數據。如此一來,就可以在這些數據結構的基礎上實現高級查找算法,這種數據結構就是 索引。
簡單一點的解釋就是:
索引是排好序的可快速查找的數據結構。
形象一點的解釋就是:
索引就好像是新華字典的查找目錄,可以幫助你快速查找到字典中的指定內容。
索引也像是圖書館的書籍查找目錄,可以幫你快速查詢到你要的書在哪。
1.2 索引的分類?
- 單值索引:一個索引只包含一個列,一個表可以有多個單列索引。
- 複合索引:一個索引包含多個列。
- 唯一索引:索引列的值必須是唯一的,但允許有多個空值。
1.3 索引的創建、查詢、刪除 的方式?
索引的創建有兩種方法:CREATE 和 ALTER 。
/*ALTER*/
ALTER TABLE tableName ADD [UNIQUE] INDEX idx_name1 (column_name1);
/*CREATE*/
CREATE [UNIQUE] INDEX idx_name1 on tableName(colum_name1);
查詢索引:
/*查詢索引*/
SHOW INDEX FROM tableNmae
刪除索引:
/*刪除索引*/
DROP INDEX [indexName] ON tableName;
下面示範一下:
用create創建索引:
用alter創建單值索引:
創建多值索引:
用alter創建多值索引也類似,這裏不演示了。
這裏順便說一下命名規範:
非唯一索引的命名(單值或多值):idx_字段名 (多值:idx_字段名1_字段名2_字段名3.....)
唯一索引命名:uni_字段名
二、高頻面試題(通過面試題更能瞭解索引)
2.1 什麼是索引?
索引(Index)是幫助MySQL高效獲取數據的數據結構。
(具體的可看上面的索引介紹。)
2.2 MySQL索引是什麼樣的數據結構?
MySQL索引主要使用的兩種數據結構:
- 哈希索引
哈希索引底層的數據結構就是哈希表,查詢很快。
所以在數據庫的大部分需求爲單條記錄查詢的時候,可以選擇哈希索引。
而其他大部分場景,一般選則BTree索引。
- BTree索引
MySQL的BTree索引用的是BTree中的B+樹。
不過對於不同的存儲引擎,實現的方式不同。
比如主要的存儲引擎MyISAM和InnoDB中的實現方法就不同。
(提到了存儲引擎MyISAM和InnoDB之後,可能會有下面三個“追命連擊”)
2.3 MySQL中的常用的存儲引擎 MyISAM與InnoDB的區別?
- InnoDB支持事務,而MyISAM不支持。
- InnoDB支持外鍵,而MyISAM不支持。
- InnoDB不支持全文索引,而MyISAM支持。
- InnoDB使用的是行級鎖,MyISAM使用的是表級鎖。
- InnoDB count(*) 時需要全表掃描,消耗資源多且速度慢;
而MyISAM 是用一個變量保存了整個表的行數,count(*)時只需讀取該變量即可,消耗資源很少且速度很快。
2.4 如何選擇存儲引擎 MyISAM與InnoDB?
- InnoDB適合寫密集的的表,MyISAM適合讀密集的表。
- 數據庫做主從分離時,一般選擇MyISAM作爲主庫的存儲引擎,InnoDB作爲從庫的存儲引擎。
- 需要支持事務,且需要支持較高併發時,選擇InnoDB。
不需要支持事務時,選擇MyISAM。
2.5 MyISAM與InnoDB實現BTree索引的方式不同在哪?
- MyISAM: B+樹葉子節點的data域存放的是數據記錄的地址。在索引檢索的時候,首先按照B+樹搜索算法搜索索引,如果指定的Key存在,則取出其 data 域的值,然後以 data 域的值爲地址讀取相應的數據記錄。這被稱爲“非聚簇索引”。
- InnoDB: 其數據文件本身就是索引文件。相比MyISAM,索引文件和數據文件是分離的,其表數據文件本身就是按B+樹組織的一個索引結構,樹的葉子節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。這被稱爲“聚簇索引(或聚集索引)”,而其餘的索引都作爲輔助索引,輔助索引的data域存儲相應記錄主鍵的值而不是地址,這也是和MyISAM不同的地方。在根據主索引搜索時,直接找到key所在的節點即可取出數據;在根據輔助索引查找時,則需要先取出主鍵的值,在走一遍主索引。 因此,在設計表的時候,不建議使用過長的字段作爲主鍵,也不建議使用非單調的字段作爲主鍵,這樣會造成主索引頻繁分裂。
2.6 爲什麼要使用索引?(索引的優點?)
-
可以大幅加快 數據的檢索速度(因爲大幅減少了檢索的數據量), 這也是創建索引的最主要的原因。
(就像使用新華字典找一個字,如果沒有目錄,我們就需要一頁一頁的來查找;而如果有目錄,我們只需查詢一下目錄就可以快速找到。) -
通過索引列對數據進行排序,降低了數據排序的成本。使服務器避免了排序與創建臨時表。
-
通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
-
將隨機IO變爲了順序IO。
-
可以加速表和表之間的連接,在實現數據的參考完整性方面特別有意義。
2.7 索引是怎麼提高查詢速度的?
- 索引將無序的數據進行了排序,我們查詢時只需查詢索引即可快速查詢到所需數據(就像使用字典的目錄來查找)。
2.8 既然索引這麼多好處,爲什麼不給表中的每一列都創建索引?(索引的缺點?)
因爲索引也有一些缺點:
- 實際上索引也是一張表,該表保存了主鍵與索引,並指向實體表的記錄,所以索引也要佔用空間。
- 索引雖然大幅提升了查詢速度,但是會降低更新表的速度。因爲在對錶中數據進行增刪改時,索引也要動態維護。這就會降低數據的維護速度(也就是降低更新表的速度)。
- 創建索引和維護索引也會耗費時間,並且數據量越大,耗費的時間越多。
2.9 使用索引有哪些注意事項?(使用索引時,SQL語句怎麼優化?)
- 要遵循最左前綴原則。
- 少在索引列上進行操作。
- 範圍條件之後的索引會失效。
- 使用模糊查詢時,%寫在最右邊,不然後面的索引會失效。
- 不等,空值,or ,這幾個會使索引失效,要少用。
- VARCHAR類型的數據,一定要記得寫引號,不然會使索引失效。
- 覆蓋索引查詢很快 ( 覆蓋索引不要寫 select * )。
- 單行訪問很慢。
不要爲了從存儲中讀取一個數據塊而去獲取其中的一行。
最好讀取的數據塊中包含儘可能多的所需要的行。
2.10 什麼是最左前綴原則?
使用多值索引時,要按索引字段的順序使用。
例如:
user表裏的屬性字段a、b、c 有一個多值索引 (a,b,c) idx_a_b_c 。
select * from user where a=1 and b=1 and c=1 ; //a,b,c可以使用索引
select * from user where a=1 ; // a可以使用索引
select * from user where a=1 and c=1; // a可以使用索引,c不能使用索引,因爲前面的b斷了。
select * from user where b=1 and c=1; // b,c 都不能使用索引,因爲前面的a斷了。
#注意
select * from user where c=1 and b=1 and a=1;
//這個a,c,c都能使用索引,因爲雖然順序不對,但是MySQL會幫我們調整順序。
2.11 什麼是覆蓋索引?
覆蓋索引,就是select的數據列只用從索引中就能夠取得,不必讀取數據行,MySQL可以利用索引返回select列表中的字段,而不用根據索引再去讀取數據文件。也就是說 查詢列要被所建立的索引覆蓋。
比如:user表有字段id、name、age、address,我們用字段name和age 建立索引 idx_name_age 。
那麼查詢時,
如果我們SQL是
select name,age from user where username='猿兄' and age = 99;
這就是覆蓋索引,要查的 name 和 age 都在索引裏,
所以我們根據索引查詢數據的時候,就可以直接從索引中獲得,而不用再去讀取數據庫。
而如果SQL是
select name,address from user where username='猿兄' and age = 99;
這樣的話,因爲address不在索引裏
當我們根據索引查詢數據時,還要再去讀取一下數據庫才能獲取address這個數據。
這樣就比較慢。