概述:
通常情況下我們需要運算元據量較大的資料庫表時候,需要關注sql的開發規範、資料索引以及慢查詢
開發規範:
1 查詢sql都應該建立索引
覆蓋索引:(這裡我們先引用百度百科的解釋)覆蓋索引是select的資料列只用從索引中就能夠取得,不必讀取資料行,換句話說查詢列要被所建的索引覆蓋。索引是高效找到行的一個方法,但是一般資料庫也能使用索引找到一個列的資料,因此它不必讀取整個行。畢竟索引葉子節點儲存了它們索引的資料;當能通過讀取索引就可以得到想要的資料,那就不需要讀取行了。一個索引包含了(或覆蓋了)滿足查詢結果的資料就叫做覆蓋索引。優點:減少了回表時間
注:主鍵索引:葉子節點儲存資料 ;輔助索引:葉子節點儲存主鍵值 (基於innoDB引擎)
我們這裡通過EXPLAIN語句查詢(留意EXPLAIN輸出的rows列,如果rows列太高,比如幾千,上萬,那麼就需要考慮是否索引不佳或連線表的順序不當)
聯合索引 + 最左匹配原則 :(這裡引用知乎普及一下知識)
聯合索引:索引的底層是一顆B+樹,聯合索引同樣是一顆B+樹,只不過聯合索引的健值數量不是一個,而是多個,資料庫依據聯合索引最左的欄位來構建B+樹。
最左匹配原則:
聯合索引(A,B,C),最左優先,以最左邊的為起點任何連續的索引都能匹配上。
1)遇到範圍查詢(>、<、between、like)就會停止匹配。
2)因為Mysql中有查詢優化器,會自動優化查詢順序,因此A,B,C順序調換不影響查詢結果。
3)沒有從最左邊開始,最後查詢沒有用到索引,用的是全表掃描
這時候一定有小夥伴會問:沒看懂,這是啥啊?你以為我看懂了?我肯定也沒啊?但是沒關係,你只要記住為什麼要使用聯合索引,或者記住他的優點是什麼?
優點:a.建立一個聯合索引,相當於建立了多個索引(比如你建立一個(a,b)聯合索引,等於建立了a,(a,b)),這樣可以減少操作和磁碟空間的開銷;
b.多索引會提高搜尋效率實現之前所說的覆蓋索引,減少回表
注:我們在使用GROUP BY、DISTINCT、ORDER BY,如果連線了多張表,ORDER BY的列應該屬於連線順序的第一張表,需要保證索引列和ORDER BY的列相同,且各列均按相同的方向進行排序
避免索引失效
索引會提高我們執行速度,但是有些操作會讓我們索引失效,所以我們要注意不能讓索引失效:
1.觸發了值型別轉換
2.對索引進行函式操作或者表示式操作
3.使用like進行了左模糊匹配或者左右模糊匹配 like "%##" ;like"%##%" (注:右模糊不會影響索引)
利用子查詢優化超多分頁場景
(這裡引用一下阿里巴巴JAVA開發手冊):MySQL 分頁並不是跳過 offset 行,而是取 offset +N 行,然後返回放棄前 offset 行,返回
N 行,所以當 offset 特別大的時候,效率就非常的低下,要麼控制返回的總頁數,要麼對超過特定閾值的頁數進行 SQL 改寫
簡單說我們應該用子查詢先把要查的範圍取出來,作為一個臨時表b
例如:select a.* from a , b where a.id = b.id
注:子查詢在效能上會比連線查詢差,所以能改成連線查詢儘量改成連線查詢。
事務隔離
這一部分我自己也不是很瞭解,最近出了一次生產事故所以特意去做了大致瞭解。大致介紹一下背景,我是個測試小羅羅,我們公司屬於物聯網公司,在邊緣端本地工控機會存放比較大量的本地資料,但是受限於工控機的配置較低所以需要定期做資料清理,就是用定時任務去刪除一些無用資料。接到這個測試任務的時候,我對資料庫事務這塊基本沒有了解,所以用例的覆蓋並沒有併發操作。上線後第二天早上就接到告警電話了,一個大型工廠使用受限,cpu已經達到90%降不下來了,主要佔比就是mysql。
覆盤:本次優化的sql語句因為使用了多表連刪,(這裡需要特別提一句,MySQL連線(JOIN)嚴重降低了併發性,對於高併發,高效能的服務,應該儘量避免連線太多表,如果可能,對於一些嚴重影響效能的SQL,建議程式在應用層就實現部分連線的功能)雖然有部分回表但基本索引是走的沒問題的,但是因為我們使用的是mysql的預設事務Repeatable read(可重複讀),在刪除語句事務執行時候上了行鎖+間隙鎖,併發的插入語句修改語句被鎖,因為資料量很大導致瞬間cpu飆升,最終導致影響工廠生產。
總結:如果有了解到你們資料庫隔離級別走的是 可重複讀 (REPEATABLE READ)一定要注意了!只有在可重複讀的隔離級別下,才會有間隙鎖。間隙鎖可能會造成死鎖!
慢查詢
當索引解決不了慢查詢時,一般由於業務表的資料量太大導致,可以考慮走redis或者增加檢視查詢
當讀寫效能均遇到瓶頸時,升級資料庫架構或者考慮分庫分表