大牛出招|分分鐘解決 MySQL 查詢速度慢與效能差
一、什麼影響了資料庫查詢速度
1.1 影響資料庫查詢速度的四個因素

1.2 風險分析


Tips: 最好不要在主庫上資料庫備份,大型活動前取消這樣的計劃。
效率低下的sql:超高的QPS與TPS。
1.大量的併發:資料連線數被佔滿(max_connection預設100,一般把連線數設定得大一些)。
2.併發量:同一時刻資料庫伺服器處理的請求數量
3.超高的CPU使用率:CPU資源耗盡出現宕機。
4.磁碟IO:磁碟IO效能突然下降、大量消耗磁碟效能的計劃任務。解決:更快磁碟裝置、調整計劃任務、做好磁碟維護。
1.3 網絡卡流量:如何避免無法連線資料庫的情況
· 減少從伺服器的數量(從伺服器會從主伺服器複製日誌)
· 進行分級快取(避免前端大量快取失效)
· 避免使用select * 進行查詢
· 分離業務網路和伺服器網路
1.4 大表帶來的問題(重要)
1.4.1 大表的特點
· 記錄行數巨大,單表超千萬
· 表資料檔案巨大,超過10個G
1.4.2 大表的危害
1.慢查詢: 很難在短時間內過濾出需要的資料
查詢字區分度低 -> 要在大資料量的表中篩選出來其中一部分資料會產生大量的磁碟io-> 降低磁碟效率
2.對DDL影響:
建立索引需要很長時間:
· MySQL -v<5.5 建立索引會鎖表
· MySQL -v>=5.5 建立索引會造成主從延遲(mysql建立索引,先在組上執行,再在庫上執行)
修改表結構需要長時間的鎖表: 會造成長時間的主從延遲('480秒延遲')
1.4.3 如何處理資料庫上的大表

難點:
1.分表主鍵的選擇
2.分表後跨分割槽資料的查詢和統計
1.5 大事務帶來的問題(重要)
1.5.1 什麼是事務

1.5.2事務的ACID屬性



隔離性等級:



redo log機制保證事務更新的 一致性 和 永續性
1.5.3 大事務

風險:鎖定資料太多,回滾時間長,執行時間長。
· 鎖定太多資料,造成大量阻塞和鎖超時;
· 回滾時所需時間比較長,且資料仍然會處於鎖定;
· 如果執行時間長,將造成主從延遲,因為只有當主伺服器全部執行完寫入日誌時,從伺服器才會開始進行同步,造成延遲。
解決思路:
· 避免一次處理太多資料,可以分批次處理;
· 移出不必要的SELECT操作,保證事務中只有必要的寫操作。
二、什麼影響了MySQL效能(非常重要)
2.1 影響效能的幾個方面
1.伺服器硬體。
2.伺服器系統(系統引數優化)。
3.儲存引擎。
MyISAM: 不支援事務,表級鎖。
InnoDB: 支援事務,支援行級鎖,事務ACID。
4.資料庫引數配置。
5.資料庫結構設計和SQL語句。(重點優化)
2.2 MySQL體系結構
分三層:客戶端->服務層->儲存引擎

1.MySQL是 外掛式的儲存引擎 ,其中儲存引擎分很多種。只要實現符合mysql儲存引擎的介面,可以開發自己的儲存引擎!
2.所有跨儲存引擎的功能都是在服務層實現的。
3.MySQL的 儲存引擎是針對表的,不是針對庫的 。也就是說在一個數據庫中可以使用不同的儲存引擎。但是不建議這樣做。
2.3 InnoDB儲存引擎
MySQL5.5及之後版本 預設的儲存引擎 :InnoDB。
2.3.1 InnoDB使用表空間進行資料儲存。
show variables like 'innodb_file_per_table
如果innodb_file_per_table 為 ON 將建立獨立的表空間,檔案為tablename.ibd;
如果innodb_file_per_table 為 OFF 將資料儲存到系統的共享表空間,檔案為ibdataX(X為從1開始的整數);
.frm:是伺服器層面產生的檔案,類似伺服器層的資料字典, 記錄表結構 。
2.3.2 (MySQL5.5預設)系統表空間與(MySQL5.6及以後預設)獨立表空間
1.1 系統表空間無法簡單的收縮檔案大小,造成空間浪費,並會產生大量的磁碟碎片。
1.2 獨立表空間可以通過optimeze table收縮系統檔案,不需要重啟伺服器也不會影響對錶的正常訪問。
2.1 如果對多個表進行重新整理時,實際上是順序進行的,會產生IO瓶頸。
2.2 獨立表空間可以同時向多個檔案重新整理資料。
強烈建立對Innodb 使用獨立表空間,優化什麼的更方便,可控。
2.3.3 系統表空間的錶轉移到獨立表空間中的方法
1、使用mysqldump 匯出所有資料庫資料(儲存過程、觸發器、計劃任務一起都要匯出 )可以在從伺服器上操作。
2、停止MYsql 伺服器,修改引數(my.cnf加入innodb_file_per_table),並刪除Inoodb相關檔案(可以重建Data目錄)。
3、重啟MYSQL,並重建Innodb系統表空間。
4、 重新匯入資料。
或者 Alter table 同樣可以的轉移,但是無法回收系統表空間中佔用的空間。
2.4 InnoDB儲存引擎的特性
2.4.1 特性一:事務性儲存引擎及兩個特殊日誌型別:Redo Log 和 Undo Log
1.Innodb 是一種 事務性儲存引擎 。
2.完全支援事務的ACID特性。
3.支援事務所需要的兩個特殊日誌型別:Redo Log 和Undo Log
Redo Log: 實現事務的永續性(已提交的事務)。
Undo Log: 未提交的事務,獨立於表空間,需要隨機訪問,可以儲存在高效能io裝置上。

2.4.2 特性二:支援行級鎖
InnoDB支援行級鎖。
行級鎖可以最大程度地支援併發。
行級鎖是由儲存引擎層實現的。
2.5 什麼是鎖
2.5.1 鎖

2.5.2 鎖型別

2.5.3 鎖的粒度
MySQL的事務支援 不是繫結在MySQL伺服器本身 , 而是與儲存引擎相關

將 table_name 加表級鎖命令:lock table table_name write; 寫鎖會阻塞其它使用者對該表的‘讀寫’操作,直到 寫鎖被釋放:unlock tables;
1.鎖的開銷越大,粒度越小,併發度越高。
2.表級鎖通常是在伺服器層實現的。
3.行級鎖是儲存引擎層實現的。innodb的鎖機制,伺服器層是不知道的
2.5.4 阻塞和死鎖
(1)阻塞是由於資源不足引起的排隊等待現象。
(2)死鎖是由於兩個物件在擁有一份資源的情況下申請另一份資源,而另一份資源恰好又是這兩物件正持有的,導致兩物件無法完成操作,且所持資源無法釋放。
2.6 如何選擇正確的儲存引擎
參考條件:
1.事務
2.備份(Innobd免費線上備份)
3.崩潰恢復
4.儲存引擎的特有特性
總結:Innodb大法好。
注意: 儘量別使用混合儲存引擎,比如回滾會出問題線上熱備問題。
2.7 配置引數
2.7.1 記憶體配置相關引數

記憶體的使用上限不能超過實體記憶體,否則容易造成記憶體溢位;(對於32位作業系統,MySQL只能試用3G以下的記憶體。)


注意: 以上四個引數是為一個執行緒分配的,如果有100個連線,那麼需要×100。

如何為快取池分配記憶體:
Innodb_buffer_pool_size,定義了Innodb所使用快取池的大小,對其效能十分重要,必須足夠大,但是過大時,使得Innodb 關閉時候需要更多時間把髒頁從緩衝池中重新整理到磁碟中;
總記憶體-(每個執行緒所需要的記憶體*連線數)-系統保留記憶體
key_buffer_size,定義了MyISAM所使用的快取池的大小,由於資料是依賴儲存作業系統快取的,所以要為作業系統預留更大的記憶體空間;
selectsum(index_length)frominformation_schema.talbeswhereengine='myisam'
注意: 即使開發使用的表全部是Innodb表,也要為MyISAM預留記憶體,因為MySQL系統使用的表仍然是MyISAM表。
max_connections 控制允許的最大連線數, 一般2000更大。
不要使用外來鍵約束保證資料的完整性。
2.8 效能優化順序
從上到下:
