分分鐘解決 MySQL 查詢速度慢與性能差

1、什麼影響了數據庫查詢速度

1.1 影響數據庫查詢速度的四個因素

    

 

1.2 風險分析前端

QPS: Queries Per Second意思是「每秒查詢率」,是一臺服務器每秒可以相應的查詢次數,是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準。
TPS:TransactionsPerSecond的縮寫,也就是事務數/秒。它是軟件測試結果的測量單位。客戶機在發送請求時開始計時,收到服務器響應後結束計時,以此來計算使用的時間和完成的事務個數。

    Tips:最好不要在主庫上數據庫備份,大型活動前取消這樣的計劃。mysql

  1. 效率低下的sql:超高的QPSTPSsql

  2. 大量的併發:數據鏈接數被佔滿(max_connection默認100,通常把鏈接數設置得大一些)。
    併發量:同一時刻數據庫服務器處理的請求數量數據庫

  3. 超高的CPU使用率:CPU資源耗盡出現宕機。緩存

  4. 磁盤IO:磁盤IO性能忽然降低、大量消耗磁盤性能的計劃任務。解決:更快磁盤設備、調整計劃任務、作好磁盤維護。性能優化

1.3 網卡流量:如何避免沒法鏈接數據庫的狀況

  • 減小從服務器的數量(從服務器會從主服務器複製日誌)服務器

  • 進行分級緩存(避免前端大量緩存失效)網絡

  • 避免使用select * 進行查詢session

  • 分離業務網絡和服務器網絡多線程

1.4 大表帶來的問題(重要

1.4.1 大表的特色

 

  • 記錄行數巨大,單表超千萬

  • 表數據文件巨大,超過10G

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屬性

一、原子性( atomicity):所有成功,所有回滾失敗。銀行存取款。
二、一致性(consistent):銀行轉帳的總金額不變。
三、隔離性(isolation):

    隔離性等級:

  • 未提交讀(READ UNCOMMITED髒讀,兩個事務之間互相可見;

  • 已提交讀(READ COMMITED)符合隔離性的基本概念,一個事務進行時,其它已提交的事物對於該事務是可見的,便可以獲取其它事務提交的數據。

  • 可重複讀(REPEATABLE READInnoDB的默認隔離等級。事務進行時,其它全部事務對其不可見,即屢次執行讀,獲得的結果是同樣的!

  • 可串行化(SERIALIZABLE) 在讀取的每一行數據上都加鎖,會形成大量的鎖超時和鎖徵用,嚴格數據一致性且沒有併發是可以使用。

    查看系統的事務隔離級別:show variables like '%iso%';
    開啓一個新事務:begin;
    提交一個事務:commit;
    修改事物的隔離級別:set session tx_isolation='read-committed';

四、持久性( DURABILITY):從數據庫的角度的持久性,磁盤損壞就不行了

    

 

 

    redo log機制保證事務更新的一致性持久性

1.5.3 大事務

運行時間長,操做數據比較多的事務;

    風險:鎖定數據太多,回滾時間長,執行時間長。

  • 鎖定太多數據,形成大量阻塞和鎖超時;

  • 回滾時所需時間比較長,且數據仍然會處於鎖定;

  • 若是執行時間長,將形成主從延遲,由於只有當主服務器所有執行完寫入日誌時,從服務器纔會開始進行同步,形成延遲。

    解決思路:

  • 避免一次處理太多數據,能夠分批次處理;

  • 移出沒必要要的SELECT操做,保證事務中只有必要的寫操做。

     

2、什麼影響了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 系統表空間的錶轉移到獨立表空間中的方法

    一、使用mysqldump 導出全部數據庫數據(存儲過程、觸發器、計劃任務一塊兒都要導出 )能夠在從服務器上操做。

    二、中止MYsql 服務器,修改參數(my.cnf加入innodb_file_per_table),並刪除Inoodb相關文件(能夠重建Data目錄)。

    三、重啓MYSQL,並重建Innodb系統表空間。

    四、 從新導入數據。

    或者 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設備上。

Undo日誌記錄某數據被修改前的值,能夠用來在事務失敗時進行 rollbackRedo日誌記錄某數據塊被修改後的值,能夠用來恢復未寫入 data file的已成功事務更新的數據。

2.4.2 特性二:支持行級鎖

  1. InnoDB支持行級鎖。

  2. 行級鎖能夠最大程度地支持併發。

  3. 行級鎖是由存儲引擎層實現的。

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如下的內存。)
肯定MySQL的 每一個鏈接 單獨使用的內存。
sort_buffer_size #定義了每一個線程排序緩存區的大小,MySQL在有查詢、須要作排序操做時纔會爲每一個緩衝區分配內存(直接分配該參數的所有內存);

join_buffer_size #定義了每一個線程所使用的鏈接緩衝區的大小,若是一個查詢關聯了多張表,MySQL會爲每張表分配一個鏈接緩衝,致使一個查詢產生了多個鏈接緩衝;

read_buffer_size #定義了當對一張MyISAM進行全表掃描時所分配讀緩衝池大小,MySQL有查詢須要時會爲其分配內存,其必須是4k的倍數;

read_rnd_buffer_size #索引緩衝區大小,MySQL有查詢須要時會爲其分配內存,只會分配須要的大小。

    注意:以上四個參數是爲一個線程分配的,若是有100個鏈接,那麼須要×100。

MySQL數據庫實例:

 ①MySQL是單進程多線程(而oracle是多進程),也就是說MySQL實例在系統上表現就是一個服務進程,即進程;

 ②MySQL實例是線程和內存組成,實例纔是真正用於操做數據庫文件的;

通常狀況下一個實例操做一個或多個數據庫;集羣狀況下多個實例操做一個或多個數據庫。

    如何爲緩存池分配內存:
    Innodb_buffer_pool_size,定義了Innodb所使用緩存池的大小,對其性能十分重要,必須足夠大,可是過大時,使得Innodb 關閉時候須要更多時間把髒頁從緩衝池中刷新到磁盤中;

總內存-(每一個線程所須要的內存*鏈接數)-系統保留內存

    key_buffer_size,定義了MyISAM所使用的緩存池的大小,因爲數據是依賴存儲操做系統緩存的,因此要爲操做系統預留更大的內存空間;

select sum(index_length) from information_schema.talbes where engine='myisam'

    注意:即便開發使用的表所有是Innodb表,也要爲MyISAM預留內存,由於MySQL系統使用的表仍然是MyISAM表。

    max_connections 控制容許的最大鏈接數, 通常2000更大。
    不要使用外鍵約束保證數據的完整性。

2.8 性能優化順序

    從上到下:

相關文章
相關標籤/搜索