-
mysql中如何定位慢查詢
表象:頁面加載過慢、接口壓測響應時間較長(超過1秒)
可以采用開源工具如Arthas以及Skywalking,使用skywalking可以檢測出哪個接口過慢。同時可以在mysql中開啟慢日志查詢,設置值為2秒,一旦sql執行超過2秒就記錄到日志中(調試階段)。 -
一條sql執行的很慢,應該如何分析?
可以采用EXPLAIN或者DESC命令獲取MySQL如何執行select語句的信息,直接在select語句前加上expla/desc。其中的possible-key表示當前sql可能會用到的索引,key表示當前sql實際命中的索引,key-len表示索引占用的大小。extra表示額外的建議。
通過key和key-len檢查是否命中了索引
通過type字段查看sql是否由進一步的優化空間,是否存在全索引掃描或全盤掃描。(index:索引樹掃描/all:全盤掃描)
通過extra判斷是否出現了回表的情況,如果出現了,可以嘗試添加索引或者修改返回字段來修復。 -
什么是索引?
索引是MySQL中高效獲取數據的數據結構(有序)主要用來提高數據檢索的效率,降低數據庫的IO成本同時降低數據排序的成本,也降低了CPU的消耗 -
索引的底層數據結構?
MySQL默認的存儲引擎InnoDB采用的是B+樹來存儲索引。采用B+樹的原因是:第一階數更多,路徑更短,第二個磁盤讀寫代價更低,非葉子節點只存儲指針,葉子節點存儲數據。第三是B+樹便于掃庫和區間查詢,因為它的葉子節點是雙向鏈表。 -
B樹和B+樹什么區別?
第一:B樹中,非葉子節點和葉子節點都放數據,而B+樹只在葉子節點存放數據,查詢時,B+樹效率更加穩定
第二:在進行范圍查詢時,B+樹效率更高,因為B+樹都在葉子節點存儲,并且葉子節點是雙向鏈表。 -
什么是聚簇索引?什么是非聚簇索引?
聚簇索引是指將數據存儲與索引放到了一塊,索引結構的葉子節點保存了一整行的數據(必須有且只有一個)
非聚簇索引(二級索引)是將數據和索引分開存儲,索引結構的葉子節點關聯的是對應數據的主鍵(可以存在多個)
一般我們自己定義的都是非聚簇索引 -
什么是回表查詢?
回表的意思就是通過二級索引(非聚簇索引)找到對應的主鍵值,然后再通過主鍵值找到聚簇索引中對應的整行數據 -
什么是覆蓋索引?
覆蓋索引是指查詢使用了索引,并且需要返回的列,在該索引中已經全部被找到。就是通過聚簇索引或者非聚簇索引一次直接命中查詢的數據,沒有觸發回表查詢。所以我們要盡量避免使用select*,盡量在返回的列中都包含添加索引的字段。 -
MySQL中超大分頁怎么處理?
超大分頁一般都是在數據量比較大的時候,我們使用limit進行分頁查詢,并且需要對數據進行排序,這個時候效率就很低。可以使用覆蓋索引來解決。通過覆蓋索引+子查詢。先分頁查詢數據的id字段,確定了id之后再通過子查詢來過濾,只查詢這個id列表中的數據就可以了。 -
索引創建的原則有哪些?
表中數據超過10w以上通常才會創建索引,并且添加索引的字段是查詢比較頻繁的字段,一般也是像作為查詢條件、排序字段或分組的字段這些。
通常創建索引使用聯合索引來創建,一條sql的返回值,盡量使用覆蓋索引。
如果一個字段內容較長,我們會考慮使用前綴索引。但索引并不是越多越好,需要控制索引的數量,添加索引也會導致增刪改查的速度變慢。 -
什么情況下索引會失效?
索引在使用的時候沒有遵守最左匹配法則。(查詢從索引的最左前列開始,并且不跳過索引中的列,如果違反則失效,如果跳過,則只有最左列索引生效)
模糊查詢時,如果%號在前面也會導致索引失效
如果在添加索引的字段上進行了運算操作或者類型轉換,索引也會失效。
字符串不加單引號,也會導致索引失效
通常情況下,想判斷這條sql是否有索引失效的情況,可以使用explain執行計劃來分析。 -
談一談你對sql優化的經驗
建表的時候,使用索引、sql語句的編寫、主從復制、讀寫分離。數據量過大的時候考慮分庫分表。
建表的時候,定義字段的時候需要結合字段的內容來選擇合適的類型,如果是數值,像tinyint、int、bigint這些類型,要根據實際情況選擇。如果是字符串類型,也是結合存儲的內容來選擇char、varchar、text類型。
使用索引的時候,比如select語句一定要指明字段名稱,不能直接使用select*,還要注意sql語句避免造成索引失效的寫法。
如果數據庫的使用場景讀的操作比較多的時候,為了避免寫的操作鎖造成的性能影響,可以采用讀寫分離的架構。讀寫分離解決的是,數據庫的寫入,影響了查詢的效率。 -
事務的特性是什么?
事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要么同時成功,或者同時失敗(ACID)
原子性、一致性、隔離性、持久性
-
并發事務帶來哪些問題?
多個事務并發進行是經常發生的,并發也是必然的。
第一個是臟讀:當一個事務正在訪問數據并對數據進行了修改,而這種修改還沒有提交到數據庫,這時另一個事務也訪問了這個數據,因為這個數據是還沒有提交的數據,所以另一個事務讀到的數據就是臟數據,
第二個是不可重復讀:比如在一個事務內多次讀同一數據,在這個事務還沒有結束的時候,另一個事務也訪問了這個數據,那么,在第一個事務中的兩次讀數據之間,由于第二個事務的修改導致第一個事務兩次讀取的數據可能不太一樣。這就發生了在一個事務內兩次督導的數據是不一樣的情況,因此稱為不可重復度。
第三個是幻讀:它發生在一個事務讀取了幾行數據,接著另一個并發事務插入了一些數據。在之后的查詢中,第一個事務就會發現多了一些原本不存在的記錄,就像發生了幻覺一樣。 -
如何解決并發事務帶來的問題,MySQL的默認隔離級別是什么?
我們可以通過對事務進行隔離來解決這些問題。
MySQL中支持四種隔離級別
第一個是未提交讀:它解決不了臟讀、不可重復讀、幻讀,平常也不用
第二個是讀已提交:他能解決臟讀
第三個是可重復讀:可以解決臟讀和不可重復讀,但不能解決幻讀(MySQL默認)
第四個是串行化:都可以解決,但性能太低。
一般都是使用可重復讀(MySQL的默認隔離級別) -
undo log和redo log的區別?
redo log日志記錄的是數據頁的物理變化,服務宕機可以用來同步數據
undo log日志主要記錄的是邏輯日志,當事務回滾時,通過逆操作恢復原來的數據
redo log保證了事務的持久性
undo log保證了事務的原子性和一致性 -
事務中的隔離性是如何保證的?
通過鎖和mvcc來實現的。mvcc就是多版本并發控制,指維護一個數據的多個版本,使得讀寫操作沒有沖突,底層實現主要分三個部分,第一個是隱藏字段,第二個是undo log日志,第三個是readView讀視圖。
隱藏字段是指:在mysql中給每個表都設置了隱藏字段,有一個是trx_id(事
務id),記錄每一次操作的事務id,是自增的;另一個字段是roll_pointer(回
滾指針),指向上一個版本的事務版本記錄地址。
undo log主要的作用是記錄回滾日志,存儲老版本數據,在內部會形成一個
版本鏈,在多個事務并行操作某一行記錄,記錄不同事務修改數據的版本,
通過roll_pointer指針形成一個鏈表。
readView解決的是一個事務查詢選擇版本的問題,在內部定義了一些匹配規
則和當前的一些事務id判斷該訪問那個版本的數據,不同的隔離級別快照讀
是不一樣的,最終的訪問的結果不一樣。如果是rc隔離級別,每一次執行快
照讀時生成ReadView,如果是rr隔離級別僅在事務中第一次執行快照讀時生
成ReadView,后續復用