MySQL 的優化方案總結

MySQL 的常見的優化方案

       性能優化(Optimize)指的是在保證系統正確性的前提下,可以更快速響應請求的一種手段。並且有些性能問題,好比慢查詢等,若是積累到必定的程度或者是遇到急速上升的併發請求以後,會致使嚴重的後果,輕則形成服務繁忙,重則致使應用不可用。它對咱們來講就像一顆即將被引爆的定時炸彈同樣,時刻威脅着咱們。所以在上線項目以前須要嚴格的把關,以確保 MySQL 可以以最優的狀態進行運行。mysql

MySQL 的優化方案有哪些?

       MySQL 數據庫常見的優化手段分爲三個層面:SQL 和索引優化、數據庫結構優化、系統硬件優化,然而每一個大的方向中又包含多個小的優化點,下面咱們具體來看看。sql

優化注意事項:

  • 依據數據而不是憑空猜想
  • 忌過早優化
  • 忌過分優化
  • 深刻理解業務
  • 性能優化是持久戰
  • 選擇合適的衡量指標、測試用例、測試環境

優化目標

  • 減小 IO 次數 IO永遠是數據庫最容易瓶頸的地方,這是由數據庫的職責所決定的,大部分數據庫操做中超過90%的時間都是 IO 操做所佔用的,減小 IO 次數是 SQL 優化中須要第一優先考慮,固然,也是收效最明顯的優化手段。
  • 下降 CPU 計算 除了 IO 瓶頸以外,SQL優化中須要考慮的就是 CPU 運算量的優化了。order by, group by,distinct … 都是消耗 CPU 的大戶(這些操做基本上都是 CPU 處理內存中的數據比較運算)。當咱們的 IO 優化作到必定階段以後,下降 CPU 計算也就成爲了咱們 SQL 優化的重要目標

優化方案一: SQL 和索引優化

  • 使用正確的索引
           索引是數據庫中最重要的概念之一,也是提升數據庫性能最有效的手段之一,它的誕生自己就是爲了提升數據查詢效率的,就像字典的目錄同樣,經過目錄能夠很快找到相關的內容。咱們應該儘量的使用主鍵查詢,而非其餘索引查詢,由於主鍵查詢不會觸發回表查詢,所以節省了一部分時間,變相的提升了查詢的性能。數據庫

    索引類型普通索引、主鍵索引、惟一索引、組合索引、全文索引
           假如咱們沒有添加索引,那麼在查詢時就會觸發全表掃描,所以查詢的數據就會不少,而且查詢效率會很低,爲了提升查詢的性能,咱們就須要給最常使用的查詢字段上,添加相應的索引,這樣才能提升查詢的性能數組

  • sql書寫時的注意緩存

    • 在 MySQL 5.0 以前的版本要儘可能避免使用 or 查詢,可使用 union 或者子查詢來替代,由於早期的 MySQL 版本使用 or 查詢可能會致使索引失效,在 MySQL 5.0 以後的版本中引入了索引合併,簡單來講就是把多條件查詢,好比 or 或 and 查詢的結果集進行合併交集或並集的功能,所以就不會致使索引失效的問題了。若是限制條件中其餘字段沒有索引,儘可能少用or。
    • 避免在 where 查詢條件中使用 != 或者 <> 操做符,由於這些操做符會致使查詢引擎放棄索引而進行全表掃描。
    • 適當使用前綴索引,MySQL 是支持前綴索引的,也就是說咱們能夠定義字符串的一部分來做爲索引。咱們知道索引越長佔用的磁盤空間就越大,那麼在相同數據頁中能放下的索引值也就越少,這就意味着搜索索引須要的查詢時間也就越長,進而查詢的效率就會下降,因此咱們能夠適當的選擇使用前綴索引,以減小空間的佔用和提升查詢效率。
    • 要儘可能避免使用 select *,而是查詢須要的字段,這樣能夠提高速度,以及減小網絡傳輸的帶寬壓力。
    • 關於JOIN優化,儘可能使用 Join 語句來替代子查詢,由於子查詢是嵌套查詢,而嵌套查詢會新建立一張臨時表,而臨時表的建立與銷燬會佔用必定的系統資源以及花費必定的時間,但 Join 語句並不會建立臨時表,所以性能會更高。
    • 咱們要儘可能使用小表驅動大表的方式進行查詢,也就是若是 B 表的數據小於 A 表的數據,那執行的順序就是先查 B 表再查 A 表。
    • 不要在列字段上進行算術運算或其餘表達式運算,不然可能會致使查詢引擎沒法正確使用索引,從而影響了查詢的效率。
    • 增長冗餘字段能夠減小大量的連表查詢,由於多張表的連表查詢性能很低,全部能夠適當的增長冗餘字段,以減小多張表的關聯查詢,這是以空間換時間的優化策略。
    • 避免類型轉換,這裏所說的「類型轉換」是指 where 子句中出現 column 字段的類型和傳入的參數類型不一致的時候發生的類型轉換。
    • 儘可能用 union all 代替 union,union 和 union all 的差別主要是前者須要將兩個(或者多個)結果集合並後再進行惟一性過濾操做,這就會涉及到排序,增長大量的 CPU 運算,加大資源消耗及延遲。因此當咱們能夠確認不可能出現重複結果集或者不在意重複結果集的時候,儘可能使用 union all 而不是 union。
    • 儘可能少排序 order by,排序操做會消耗較多的 CPU 資源,因此減小排序能夠在緩存命中率高等 IO 能力足夠的場景下會較大影響 SQL 的響應時間。若是排序字段沒有用到索引,就儘可能少排序。
    • SQL語句中IN包含的值不該過多,MySQL對於IN作了相應的優化,即將IN中的常量所有存儲在一個數組裏面,並且這個數組是排好序的。可是若是數值較多,產生的消耗也是比較大的。
    • 當只須要一條數據的時候,使用limit 1,這是爲了使EXPLAIN中type列達到const類型。
    • 區分in和exists, not in和not exists。
    • 使用合理的分頁方式以提升分頁的效率。
    • 分段查詢
    • 避免在 where 子句中對字段進行 null 值判斷
    • 不建議使用%前綴模糊查詢,若是使用%前綴來模糊查詢,建議使用全文索引。
    • 對於聯合索引來講,要遵照最左前綴法則。好比:組合索引(a,b,c)三列,咱們可使用(a)、(a,b)、(a,c)、(b、c)、(a,b,c)可是不能以(b,a)、(c,a)、(c,b)等組合使用不然致使索引失效。
    • 必要時可使用force index來強制查詢走某個索引。

以上這些優化方案咱們均可以經過EXPLAIN方式來驗證。性能優化

在這裏插入圖片描述
EXPLAIN各個字段詳介紹:
在這裏插入圖片描述
type字段值以下:
在這裏插入圖片描述

優化方案二:數據庫結構優化

最小數據長度服務器

       通常說來數據庫的表越小,那麼它的查詢速度就越快,所以爲了提升表的效率,應該將表的字段設置的儘量小,好比身份證號,能夠設置爲 char(18) 就不要設置爲 varchar(18)。網絡

使用最簡單數據類型併發

       能使用 int 類型就不要使用 varchar 類型,由於 int 類型比 varchar 類型的查詢效率更高。性能

儘可能少定義 text 類型

       text 類型的查詢效率很低,若是必需要使用 text 定義字段,能夠把此字段分離成子表,須要查詢此字段時使用聯合查詢,這樣能夠提升主表的查詢效率。

選擇合適的存儲引擎

       存儲引擎類型:MyISAM、InnoDB、MEMORY、MERGE、TokuDB、CSV、Archive

       MyISAM:若是應用是以讀操做和插入操做爲主,只有不多的更新和刪除操做,而且對事務的完整性、併發性要求不是很高,那麼選擇該存儲引擎是很是合適的。MyISAM是在Web、數據倉庫和其餘應用環境下最常使用的存儲引擎之一。

        InnoDB:用於事務處理應用程序,支持外鍵。若是應用程序對事務的完整性有比較高的要求,在併發條件下要求數據的一致性,數據操做除了插入和查詢外,還包括不少的更新、刪除操做,那麼InnoDB存儲引擎是比較合適的選擇。InnoDB存儲引擎除了有效地下降因爲刪除和更新致使地鎖定,還能夠確保事務地完整提交(Commit)和回滾(Rollback),對於相似計費系統或者財務系統等對數據準確性要求較高地系統,InnoDB都是合適地選擇。

       MEMORY:將全部數據保存在RAM中,在須要快速定位記錄和其餘相似數據的環境下,可提供極快的訪問。MEMORY的缺陷是對錶的大小有限制,太大的表沒法緩存在內存中,其次是要確保表的數據能夠恢復,數據庫異常終止後表中的數據是能夠恢復的。MEMORY表一般用於更新不太頻繁的小表,用以快速訪問結果。

       MERGE:用於將一系列等同地MyISAM表以邏輯方式組合在一塊兒,並做爲一個對象引用它們,MERGE表地優勢在於能夠突破對單個MyISAM表大小的限制,而且經過將不一樣的表分佈在多個磁盤上,能夠有效地改善MERGE表的訪問效率,這對於諸如數據倉庫等VLDB環境十分適合。屬於第三方存儲引擎 ,高寫性能高壓縮率,支持事務處理的MySQL和MariaDB的存儲引擎,支持大多數在線DDL操做。

       TokuDB:使用Fractal樹索引保證高效的插入性能;優秀的壓縮特性,比InnoDB高近10倍;Hot Schema Changes特性支持在線建立索引和添加、刪除屬性列等DDL操做。使用Bulk Loader達到快速加載大量數據;提供了主從延遲消除技術;支持ACID和MVCC。

三種常見的存儲引擎對比:

在這裏插入圖片描述
適當分表、分庫策略

       分表和分庫方案也是咱們常常說的垂直分隔(分表)和水平分隔(分庫)。

       分表是指當一張表中的字段更多時,能夠嘗試將一張大表拆分爲多張子表,把使用比較高頻的主信息放入主表中,其餘的放入子表,這樣咱們大部分查詢只須要查詢字段更少的主表就能夠完成了,從而有效的提升了查詢的效率。

       分庫是指將一個數據庫分爲多個數據庫。好比咱們把一個數據庫拆分爲了多個數據庫,一個主數據庫用於寫入和修改數據,其餘的用於同步主數據並提供給客戶端查詢,這樣就把一個庫的讀和寫的壓力,分攤給了多個庫,從而提升了數據庫總體的運行效率。

優化方案三: 系統硬件優化

MySQL 對硬件的要求主要體如今三個方面:磁盤、網絡和內存。

磁盤

       磁盤尋道能力(磁盤I/O),以目前高轉速SCSI硬盤(7200轉/秒)爲例,這種硬盤理論上每秒尋道7200次,這是物理特性決定的,沒有辦法改變;磁盤應該儘可能使用有高性能讀寫能力的磁盤,好比固態硬盤,這樣就能夠減小 I/O 運行的時間,從而提升了 MySQL 總體的運行效率。
       磁盤也能夠儘可能使用多個小磁盤而不是一個大磁盤,由於磁盤的轉速是固定的,有多個小磁盤就至關於擁有多個並行運行的磁盤同樣。

網絡

       保證網絡寬帶的通暢(低延遲)以及夠大的網絡帶寬是 MySQL 正常運行的基本條件,若是條件容許的話也能夠設置多個網卡,以提升網絡高峯期 MySQL 服務器的運行效率。
       DNS配置 儘可能使用skip-name-resolve來減小因解析帶來的沒必要要麻煩。
       檢查網絡的ping 丟包率。
       經過優化/etc/sysctl.cnf 中的網絡參數,提高性能。

內存

       MySQL 服務器的內存越大,那麼存儲和緩存的信息也就越多,而內存的性能是很是高的,從而提升了整個 MySQL 的運行效率。

知識擴展

       慢查詢慢查詢一般的排查手段是先使用慢查詢日誌功能,查詢出比較慢的 SQL 語句,而後再經過 explain 來查詢 SQL 語句的執行計劃,最後分析並定位出問題的根源,再進行處理(上文中有介紹到)。

       慢查詢日誌指的是在 MySQL 中能夠經過配置來開啓慢查詢日誌的記錄功能,超過 long_query_time 值的 SQL 將會被記錄在日誌中。咱們能夠經過設置「slow_query_log=1」來開啓慢查詢,它的開啓方式有兩種:

       經過 MySQL 命令行的模式進行開啓,只須要執行「set global slow_query_log=1」便可,然而這種配置模式再重啓 MySQL 服務以後就會失效;        另外一種方式可經過修改 MySQL 配置文件的方式進行開啓,咱們須要配置 my.cnf中的「slow_query_log=1」便可,而且能夠經過設置「slow_query_log_file=/tmp/mysql_slow.log」來配置慢查詢日誌的存儲目錄,但這種方式配置完成以後須要重啓 MySQL 服務器纔可生效。
       須要注意的是,在開啓慢日誌功能以後,會對 MySQL 的性能形成必定的影響,所以在生產環境中要慎用此功能。

====================== END =========================

相關文章
相關標籤/搜索