高性能MySQ

書籍推薦

《高性能MySQL : 第3版》html

文字教程推薦

MySQL 教程(菜鳥教程)mysql

MySQL教程(易百教程)算法

視頻教程推薦

基礎入門: 與MySQL的零距離接觸-慕課網sql

Mysql開發技巧: MySQL開發技巧(一)  MySQL開發技巧(二)  MySQL開發技巧(三)數據庫

Mysql5.7新特性及相關優化技巧: MySQL5.7版本新特性  性能優化之MySQL優化segmentfault

MySQL集羣(PXC)入門  MyCAT入門及應用緩存

常見問題總結

  • ①存儲引擎

    MySQL常見的兩種存儲引擎:MyISAM與InnoDB的愛恨情仇性能優化

  • ②字符集及校對規則

    字符集指的是一種從二進制編碼到某類字符符號的映射。校對規則則是指某種字符集下的排序規則。Mysql中每一種字符集都會對應一系列的校對規則。bash

    Mysql採用的是相似繼承的方式指定字符集的默認值,每一個數據庫以及每張數據表都有本身的默認值,他們逐層繼承。好比:某個庫中全部表的默認字符集將是該數據庫所指定的字符集(這些表在沒有指定字符集的狀況下,纔會採用默認字符集) PS:整理自《Java工程師修煉之道》網絡

    詳細內容能夠參考: MySQL字符集及校對規則的理解

  • ③索引相關的內容(數據庫使用中很是關鍵的技術,合理正確的使用索引能夠大大提升數據庫的查詢性能)

      Mysql索引使用的數據結構主要有BTree索引哈希索引 。對於哈希索引來講,底層的數據結構就是哈希表,所以在絕大多數需求爲單條記錄查詢的時候,能夠選擇哈希索引,查詢性能最快;其他大部分場景,建議選擇BTree索引。

      Mysql的BTree索引使用的是B數中的B+Tree,但對於主要的兩種存儲引擎的實現方式是不一樣的。

      MyISAM: B+Tree葉節點的data域存放的是數據記錄的地址。在索引檢索的時候,首先按照B+Tree搜索算法搜索索引,若是指定的Key存在,則取出其 data 域的值,而後以 data 域的值爲地址讀取相應的數據記錄。這被稱爲「非聚簇索引」。

      InnoDB: 其數據文件自己就是索引文件。相比MyISAM,索引文件和數據文件是分離的,其表數據文件自己就是按B+Tree組織的一個索引結構,樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,所以InnoDB表數據文件自己就是主索引。這被稱爲「聚簇索引(或彙集索引)」。而其他的索引都做爲輔助索引,輔助索引的data域存儲相應記錄主鍵的值而不是地址,這也是和MyISAM不一樣的地方。在根據主索引搜索時,直接找到key所在的節點便可取出數據;在根據輔助索引查找時,則須要先取出主鍵的值,再走一遍主索引。 所以,在設計表的時候,不建議使用過長的字段做爲主鍵,也不建議使用非單調的字段做爲主鍵,這樣會形成主索引頻繁分裂。 PS:整理自《Java工程師修煉之道》

    詳細內容能夠參考:

    乾貨:mysql索引的數據結構

    MySQL優化系列(三)--索引的使用、原理和設計優化

    數據庫兩大神器【索引和鎖】

  • ④查詢緩存的使用

    my.cnf加入如下配置,重啓Mysql開啓查詢緩存

    query_cache_type=1
    query_cache_size=600000
    複製代碼

    Mysql執行如下命令也能夠開啓查詢緩存

    set global  query_cache_type=1;
    set global  query_cache_size=600000;
    複製代碼

    如上,開啓查詢緩存後在一樣的查詢條件以及數據狀況下,會直接在緩存中返回結果。這裏的查詢條件包括查詢自己、當前要查詢的數據庫、客戶端協議版本號等一些可能影響結果的信息。所以任何兩個查詢在任何字符上的不一樣都會致使緩存不命中。此外,若是查詢中包含任何用戶自定義函數、存儲函數、用戶變量、臨時表、Mysql庫中的系統表,其查詢結果也不會被緩存。

    緩存創建以後,Mysql的查詢緩存系統會跟蹤查詢中涉及的每張表,若是這些表(數據或結構)發生變化,那麼和這張表相關的全部緩存數據都將失效。

    緩存雖然可以提高數據庫的查詢性能,可是緩存同時也帶來了額外的開銷,每次查詢後都要作一次緩存操做,失效後還要銷燬。 所以,開啓緩存查詢要謹慎,尤爲對於寫密集的應用來講更是如此。若是開啓,要注意合理控制緩存空間大小,通常來講其大小設置爲幾十MB比較合適。此外,還能夠經過sql_cache和sql_no_cache來控制某個查詢語句是否須要緩存:

    select sql_no_cache count(*) from usr;
    複製代碼
  • ⑤事務機制

    關係性數據庫須要遵循ACID規則,具體內容以下:

事務的特性

  1. 原子性: 事務是最小的執行單位,不容許分割。事務的原子性確保動做要麼所有完成,要麼徹底不起做用;
  2. 一致性: 執行事務先後,數據庫從一個一致性狀態轉換到另外一個一致性狀態。
  3. 隔離性: 併發訪問數據庫時,一個用戶的事物不被其餘事務所幹擾,各併發事務之間數據庫是獨立的;
  4. 持久性: 一個事務被提交以後。它對數據庫中數據的改變是持久的,即便數據庫 發生故障也不該該對其有任何影響。

爲了達到上述事務特性,數據庫定義了幾種不一樣的事務隔離級別:

  • READ_UNCOMMITTED(未提交讀): 最低的隔離級別,容許讀取還沒有提交的數據變動,可能會致使髒讀、幻讀或不可重複讀

  • READ_COMMITTED(提交讀): 容許讀取併發事務已經提交的數據,能夠阻止髒讀,可是幻讀或不可重複讀仍有可能發生

  • REPEATABLE_READ(可重複讀): 對同一字段的屢次讀取結果都是一致的,除非數據是被自己事務本身所修改,能夠阻止髒讀和不可重複讀,但幻讀仍有可能發生。

  • SERIALIZABLE(串行): 最高的隔離級別,徹底服從ACID的隔離級別。全部的事務依次逐個執行,這樣事務之間就徹底不可能產生干擾,也就是說,該級別能夠防止髒讀、不可重複讀以及幻讀。可是這將嚴重影響程序的性能。一般狀況下也不會用到該級別。

    這裏須要注意的是:Mysql 默認採用的 REPEATABLE_READ隔離級別 Oracle 默認採用的 READ_COMMITTED隔離級別.

    事務隔離機制的實現基於鎖機制和併發調度。其中併發調度使用的是MVCC(多版本併發控制),經過行的建立時間和行的過時時間來支持併發一致性讀和回滾等特性。

    詳細內容能夠參考: 多是最漂亮的Spring事務管理詳解

  • ⑥鎖機制與InnoDB鎖算法

    MyISAM和InnoDB存儲引擎使用的鎖:

    • MyISAM採用表級鎖(table-level locking)。
    • InnoDB支持行級鎖(row-level locking)和表級鎖,默認爲行級鎖

    表級鎖和行級鎖對比:

    • 表級鎖: Mysql中鎖定 粒度最大 的一種鎖,對當前操做的整張表加鎖,實現簡單,資源消耗也比較少,加鎖快,不會出現死鎖。其鎖定粒度最大,觸發鎖衝突的機率最高,併發度最低,MyISAM和 InnoDB引擎都支持表級鎖。
    • 行級鎖: Mysql中鎖定 粒度最小 的一種鎖,只針對當前操做的行進行加鎖。 行級鎖能大大減小數據庫操做的衝突。其加鎖粒度最小,併發度高,但加鎖的開銷也最大,加鎖慢,會出現死鎖。

    詳細內容能夠參考: Mysql鎖機制簡單瞭解一下

    InnoDB存儲引擎的鎖的算法有三種:

    • Record lock:單個行記錄上的鎖
    • Gap lock:間隙鎖,鎖定一個範圍,不包括記錄自己
    • Next-key lock:record+gap 鎖定一個範圍,包含記錄自己

    相關知識點:

    1. innodb對於行的查詢使用next-key lock
    2. Next-locking keying爲了解決Phantom Problem幻讀問題
    3. 當查詢的索引含有惟一屬性時,將next-key lock降級爲record key
    4. Gap鎖設計的目的是爲了阻止多個事務將記錄插入到同一範圍內,而這會致使幻讀問題的產生
    5. 有兩種方式顯式關閉gap鎖:(除了外鍵約束和惟一性檢查外,其他狀況僅使用record lock) A. 將事務隔離級別設置爲RC B. 將參數innodb_locks_unsafe_for_binlog設置爲1
  • ⑦大表優化

    當MySQL單表記錄數過大時,數據庫的CRUD性能會明顯降低,一些常見的優化措施以下:

  1. 限定數據的範圍: 務必禁止不帶任何限制數據範圍條件的查詢語句。好比:咱們當用戶在查詢訂單歷史的時候,咱們能夠控制在一個月的範圍內。;

  2. 讀/寫分離: 經典的數據庫拆分方案,主庫負責寫,從庫負責讀; 3 . 垂直分區:

    根據數據庫裏面數據表的相關性進行拆分。 例如,用戶表中既有用戶的登陸信息又有用戶的基本信息,能夠將用戶表拆分紅兩個單獨的表,甚至放到單獨的庫作分庫。

    簡單來講垂直拆分是指數據表列的拆分,把一張列比較多的表拆分爲多張表。 以下圖所示,這樣來講你們應該就更容易理解了。

    垂直拆分的優勢: 可使得行數據變小,在查詢時減小讀取的Block數,減小I/O次數。此外,垂直分區能夠簡化表的結構,易於維護。

    垂直拆分的缺點: 主鍵會出現冗餘,須要管理冗餘列,並會引發Join操做,能夠經過在應用層進行Join來解決。此外,垂直分區會讓事務變得更加複雜;

  3. 水平分區:

    保持數據表結構不變,經過某種策略存儲數據分片。這樣每一片數據分散到不一樣的表或者庫中,達到了分佈式的目的。 水平拆分能夠支撐很是大的數據量。

    水平拆分是指數據錶行的拆分,表的行數超過200萬行時,就會變慢,這時能夠把一張的表的數據拆成多張表來存放。舉個例子:咱們能夠將用戶信息表拆分紅多個用戶信息表,這樣就能夠避免單一表數據量過大對性能形成影響。

    數據庫水平拆分

    水平拆分能夠支持很是大的數據量。須要注意的一點是:分表僅僅是解決了單一表數據過大的問題,但因爲表的數據仍是在同一臺機器上,其實對於提高MySQL併發能力沒有什麼意義,因此 水平拆分最好分庫

    水平拆分可以 支持很是大的數據量存儲,應用端改造也少,但 分片事務難以解決 ,跨界點Join性能較差,邏輯複雜。《Java工程師修煉之道》的做者推薦 儘可能不要對數據進行分片,由於拆分會帶來邏輯、部署、運維的各類複雜度 ,通常的數據表在優化得當的狀況下支撐千萬如下的數據量是沒有太大問題的。若是實在要分片,儘可能選擇客戶端分片架構,這樣能夠減小一次和中間件的網絡I/O。

    下面補充一下數據庫分片的兩種常見方案:

    • 客戶端代理: 分片邏輯在應用端,封裝在jar包中,經過修改或者封裝JDBC層來實現。 噹噹網的 Sharding-JDBC 、阿里的TDDL是兩種比較經常使用的實現。
    • 中間件代理: 在應用和數據中間加了一個代理層。分片邏輯統一維護在中間件服務中。 咱們如今談的 Mycat 、360的Atlas、網易的DDB等等都是這種架構的實現。

詳細內容能夠參考: MySQL大表優化方案

相關文章
相關標籤/搜索