1.1慢查詢
1.1.1 是否命中索引
提起慢查詢,我們馬上就會想到加索引。如果一條SQL沒加索引,或者沒有命中索引的話,就會產生慢查詢。
索引哪些情況會失效?
-
查詢條件包含or,可能導致索引失效
-
如果字段類型是字符串,where時一定用引號括起來,否則索引失效
-
like通配符可能導致索引失效。
-
聯合索引,查詢時的條件列不是聯合索引中的第一個列,索引失效。
-
在索引列上使用mysql的內置函數,索引失效。
-
對索引列運算(如,+、-、*、/),索引失效。
-
索引字段上使用(!= 或者 < >,not in)時,可能會導致索引失效。
-
索引字段上使用is null, is not null,可能導致索引失效。
-
左連接查詢或者右連接查詢查詢關聯的字段編碼格式不一樣,可能導致索引失效。
1.1.2 數據量大,考慮分庫分表
單表數據量太大,就會影響SQL執行性能。我們知道索引數據結構一般是B+樹。因此,數據量大的時候,建議分庫分表。分庫分表的中間件有mycat、sharding-jdbc。
1.2 死鎖
死鎖是指兩個或多個事務在同一資源上相互占用,并請求鎖定對方的資源,從而導致惡性循環的現象。
暫時無法在飛書文檔外展示此內容
MySQL內部有一套死鎖檢測機制,一旦發生死鎖會立即回滾一個事務,讓另一個事務執行下去。但死鎖有資源的利用率降低、進程得不到正確結果等危害。
1.2.1 9種情況的SQL加鎖分析
要避免死鎖,需要學會分析:一條SQL的加鎖是如何進行的?一條SQL加鎖,可以分9種情況進行探討:
-
組合一:id列是主鍵,RC隔離級別
-
組合二:id列是二級唯一索引,RC隔離級別
-
組合三:id列是二級非唯一索引,RC隔離級別
-
組合四:id列上沒有索引,RC隔離級別
-
組合五:id列是主鍵,RR隔離級別
-
組合六:id列是二級唯一索引,RR隔離級別
-
組合七:id列是二級非唯一索引,RR隔離級別
-
組合八:id列上沒有索引,RR隔離級別
-
組合九:Serializable隔離級別
1.2.2 如何分析解決死鎖?
分析解決死鎖的步驟如下:
-
模擬死鎖場景
-
show engine innodb status;查看死鎖日志
-
找出死鎖SQL
-
SQL加鎖分析
-
分析死鎖日志(持有什么鎖,等待什么鎖)
-
熟悉鎖模式兼容矩陣,InnoDB存儲引擎中鎖的兼容性矩陣。
1.3 一些SQL的經典注意點
1.3.1 limit大分頁問題
limit大分頁是一個非常經典的SQL問題,我們一般有這3種對應的解決方案
方案一: 如果id是連續的,可以這樣,返回上次查詢的最大記錄(偏移量),再往下limit
select id,name from employee where id>1000000 limit 10.
方案二: 在業務允許的情況下限制頁數:
建議跟業務討論,有沒有必要查這么深度的分頁啦。因為絕大多數用戶都不會往后翻太多頁。谷歌搜索頁也是限制了頁數,因此不存在limit大分頁問題。
方案三: 利用延遲關聯或者子查詢優化超多分頁場景。(先快速定位需要獲取的id段,然后再關聯)
SELECT a.* FROM employee a, (select id from employee where 條件 LIMIT 1000000,10 ) b where a.id=b.id
1.3.2 修改、查詢數據量多時,考慮分批進行。
我們更新或者查詢數據庫數據時,盡量避免循環去操作數據庫,可以考慮分批進行。比如你要插入10萬數據的話,可以一次插入500條。