1. 什么是索引?
索引是一種數據結構,可以幫助我們快速進行數據的查找;2. 索引是個什么樣的數據結構呢?
索引的數據結構和具體的存儲引擎的實現有關,在mysql中常用索引有hash索引和B+樹索引,innoDB中默認使用B+樹索引;
3. Hash索引和B+樹所有有什么區別或者說優劣呢?
兩者的原理:
hash索引:底層是hash表,通過調用hash函數獲得響應的鍵值,之后通過這個鍵值回表查詢獲得實際的數據;
hash索引的優勢在於等值查詢的速度,無法進行范圍查(因為hash索引順序與原順序不一致).無法使用
索引排序,不支持模糊查詢,無法避免回表數據查詢,並且等值查詢的效率並不穩定,有可能效率很差;
B+樹索引:底層是多路平衡查找樹,每次查詢都從根節點出發,查找到葉子節點可以獲得所查鍵值,
然后根據查詢判斷是否需要回表查詢數據.B樹因為數據結構優勢天然支持范圍查詢,
B+樹的查詢效率比較穩定,對於所有的查詢都是從根節點到葉子節點,且樹的高度較低.
B+樹在符合某些條件(聚簇索引,覆蓋索引等)的時候可以只通過索引完成查詢
所以大多數情況下,B+樹索引相對更好.
4. 上面提到了B+樹在滿足聚簇索引和覆蓋索引的時候不需要回表查詢數據,什么是聚簇索引?
B樹索引中,葉子節點可能存儲了當前的key值,也可能存儲了當前的key值以及整行的數據,
這就是聚簇索引和非聚簇索引;在InnoDB中,只有主鍵的叫聚簇索引,如果沒有住進,則挑選
一個唯一鍵建立聚簇索引,如果唯一鍵也沒有,則隱式生成一個鍵建立聚簇索引.
當查詢使用聚簇索引時,在對應的葉子節點,可以獲取到整行數據,因此不用再次進行回表查詢.
5. 非聚簇索引一定會回表查詢嗎?
不一定,這涉及到查詢語句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再進行回表查詢.
舉個簡單的例子,假設我們在員工表的年齡上建立了索引,那么當進行select age from employee where age < 20的查詢時,
在索引的葉子節點上,已經包含了age信息,不會再次進行回表查詢.
6. 在建立索引的時候,都有哪些需要考慮的因素呢?
1.字段使用頻率;2.如果是聯合索引,需要按照索引時的字段順序使用,否則無法命中索引;3.過多的索引反而會影響數據庫的查詢效率
7. 聯合索引是什么?為什么需要注意聯合索引中的順序?
mysql可以使用多個字段同時建立一個索引,叫做聯合索引,同時聯合索引在建立時要留意將高頻的字段索引放在前面
8. 創建的索引有沒有被使用到?或者說怎么才可以知道這條語句運行很慢的原因?
explain命令查看sql語句的執行計划;
9. 那么在哪些情況下會發生針對該列創建了索引但是在查詢的時候並沒有使用呢?
1.使用!=查詢;
2.列參與了數學運算或者函數;
3.查詢字符時like的條件里面出現通配符%;
4.mysql分析全表掃描回避使用索引塊的時候;
5.使用聯合索引時,前面一個條件為范圍查詢,后面的基石符合最左前綴原則也不能用索引了
10. 什么是事務?
一系列滿足ACID特性的操作.這些操作,要么全成功、要么全失敗;
11.ACID是什么?可以詳細說一下嗎?
A:Atomicity原子性,不可分割
C:Consistency 一致性,
I:Isolation 隔離性;
D:Durability 持久性;
12.同時有多個事務在進行會怎么樣呢?
多事務會產生問題:臟讀,幻讀,不可重復讀;
13. 怎么解決這些問題呢?MySQL的事務隔離級別了解嗎?
Mysql有四種事務隔離級別:未提交讀;已提交讀;可重復讀(mysql默認);可串行化;
14. Innodb使用的是哪種隔離級別呢?
InnoDB默認使用的是可重復讀隔離級別.
15.對MySQL的鎖了解嗎?
mysql從類別上分:有共享鎖和排他鎖
共享鎖用在DQL查詢上,也叫讀鎖,當讀取數據時,對數據加上共享鎖,共享鎖可以同時加多個查詢用戶;
排他鎖用在DML增刪改上,也叫寫鎖,數據寫入時,數據加鎖,只有當前用戶持有,其他執行相同DML操作的用戶無法訪問,被互斥
鎖從粒度區分:行,頁,表等幾個等級的鎖;
16.為什么要盡量設定一個主鍵?主鍵使用自增ID還是UUID?
主鍵可以保證整張表的唯一性,主鍵也可以快速定位行數據;
推薦自增ID,因為在默認的InnoDB中,主鍵索引是作為聚簇索引存在的.自增索引可以保證數據的順序.
17.字段為什么要求定義為not null?
null值會占用更多的空間維護,所以如果可以的話定義一張表的時候盡量減少允許非空列的存在;
18.如果要存儲用戶的密碼散列,應該使用什么字段進行存儲?
固定長度的字符應該使用char,這樣可以節省空間並且提高效率;
19. MySQL支持哪些存儲引擎?
其實mysql支持很多種存儲引擎,InnoDB,MyISAM等等
但是選擇InnoDB引擎相對合適,也是mysql默認的存儲引擎;
InnoDB支持事務,鎖的粒度是行級鎖,支持MVCC,支持外鍵,不支持全文索引相對性能優秀;
20.MySQL中的varchar和char有什么區別?
char是定長的字符串,空間占用是固定的而var是變長字符串,存儲時如果沒有指定長度會默認采用最大長度存儲,
從檢索效率上講char的效率也更高;
21.varchar(10)和int(10)代表什么含義?
varchar僅代表申請的長度空間,也就是最大存儲數據的長度.
22.超大分頁怎么處理?
select * from table where id in (select id from table where age > 20 limit 1000000,10)
.
這樣雖然也load了一百萬的數據,但是由於索引覆蓋,要查詢的所有字段都在索引中,所以速度會很快
解決超大分頁,其實主要是靠緩存,可預測性的提前查到內容,緩存至redis等k-V數據庫中,直接返回即可.
在阿里巴巴《Java開發手冊》中,對超大分頁的解決辦法是類似於上面提到的第一種
23.對慢查詢都怎么優化過?
sql優化:
盡量使用索引查詢,少用!=或者in這樣的操作符會導致全表掃描;
表數據盡量不要使用null;
盡量少用字符串的模糊通配符%查詢;
盡量指定查詢的結果字段,而不是用*;
分批處理大批量的數據查詢;
條件語句exists效率更高;
select into少用;
另外如果表中數據量過大,可以考慮橫向分表或者縱向分表;
24.三個范式
第一范式: 每個列都不可以再拆分.
第二范式: 每一行的數據只能與其中一列相關,即一行數據只做一件事。只要數據列中出現數據重復,就要把表拆分開來
第三范式: 非主鍵列只依賴於主鍵,不依賴於其他非主鍵.數據不能存在傳遞關系,即沒個屬性都跟主鍵有直接關系而不是間接關系