mysql筆記01 MySQL架構與歷史、Schema與數據類型優化

MySQL架構與歷史html

1. MySQL架構推薦參考:http://www.cnblogs.com/baochuan/archive/2012/03/15/2397536.html數據庫

2. MySQL會解析查詢,並建立內部數據結構(解析樹),而後對其進行各類優化,包括重寫查詢、決定表的讀取順序,以及選擇合適的索引等。用戶能夠經過特殊的關鍵字提示(hint)優化器,影響它的決策過程。緩存

    也能夠請求優化器解釋(explain)優化過程的各個因素,使用戶能夠知道服務器如何進行優化決策的,並提供一個參考基準,便於用戶重構查詢和schema、修改相關配置,使應用盡量高效運行。安全

3. 對於SELECT語句,在解析查詢以前,服務器先檢查查詢緩存(Query Cache),若是可以在其中找到對應的查詢,服務器就不會再執行查詢解析、優化和執行的整個過程,而是直接返回查詢緩存中的結果集。服務器

4. 讀鎖(共享鎖)是共享的,或者說是互相不阻塞的。多個客戶在同一時刻能夠同時讀取同一個資源,而互不干擾。數據結構

    寫鎖(排他鎖)則是排他的,也就是說一個寫鎖會阻塞其餘的寫鎖和讀鎖,這是出於安全策略的考慮,只有這樣才能確保在給定的時間裏,只有一個用戶能執行寫入,並防止其餘用戶讀取正在寫入的同一資源。架構

5. 鎖粒度:鎖的各類操做,包括得到鎖、檢查鎖是否已經解除、釋放鎖等,都會增長系統的開銷。若是系統花費大量的時間來管理鎖,而不是存儲數據,那麼系統性能可能會受到影響。併發

    鎖策略:就是在鎖的開銷和數據安全性之間尋求平衡。框架

    表鎖(table lock):表鎖是MySQL中最基本的鎖策略,而且是開銷最小的鎖策略。寫鎖比讀鎖有更高的優先級,所以一個寫鎖請求可能會被插入到讀鎖隊列的前面(寫鎖能夠插入到鎖隊列中讀鎖的前面,反之ide

                               讀鎖則不能插入到寫鎖的前面)。

    行級鎖(row lock):行級鎖能夠最大程度地支持併發處理(同時也會帶來最大化的鎖開銷)。

6. 事務:事務就是一組原子性的SQL查詢,或者說一個獨立的工做單元。事務內的語句,要麼所有執行成功,要麼所有執行失敗。

    1). ACID:

          原子性(atomicity):一個事務必須視爲一個不可分割的最小工做單元,整個事務中全部操做要麼所有提交成功,要麼所有失敗回滾,對於一個事務來講,不可能只執行其中的一部分操做,這就是事務的原子性。

         一致性(consistency): 數據庫老是從一個一致性狀態轉換到另外一個一致性狀態。

         隔離性(isolation):一般來講,一個事務所作的修改在最終提交之前,對其餘事務老是不可見的。

         持久性(durability):一旦事務提交,則其所作的修改就會永久保存到數據庫中。此時,即便系統崩潰,修改的數據也不會丟失。

   2). 事務處理過程當中額外的安全性,也會須要數據庫系統作更多的額外工做,影響運行效率。

   3). 隔離級別:

        READ UNCOMMITTED(未提交讀):事務能夠讀取未提交的數據,這也被稱爲髒讀(Dirty Read)

        READ COMMITTED(提交讀):大多數數據庫的默認隔離級別,但MySQL不是。這個級別有時候也叫不可重複讀,由於兩次執行一樣的查詢,可能會獲得不同的結果。

                                                是指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,

                                                那麼第一個事務兩次讀到的的數據多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀。

        REPEATABLE READ(可重複讀):解決了髒讀問題。該級別保證了同一個事務中屢次讀取一樣記錄的結果是一致的。MySQL的默認隔離級別。

        SERIALIZABLE(可串行化):最高隔離級別,經過強制事務串行執行,避免了前面說的幻讀問題。只有在數據很是中的時候才使用。

   4). 死鎖:指兩個或多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而致使惡性循環的現象。當多個事務試圖以不一樣的順序鎖定資源時,就可能會產生死鎖。

        InnoDB目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾。

   5). 使用事務日誌,存儲引擎在修改表的數據時,只須要修改其內存拷貝,再把修改行爲記錄到持久在硬盤的事務日誌中,而不用每次都將修改的數據自己持久到硬盤。事務採用的是追加的方式。事務日誌持久化

         之後,內存中被修改的數據在後臺能夠慢慢地刷回到磁盤。若是數據的日誌已經記錄到事務日誌並持久化,但數據自己尚未回寫磁盤,此時系統崩潰,存儲引擎在重啓時可以自動恢復這部分修改的數據。

   6). MySQL中的事務:

         a. 自動提交(AUTOMCOMMIT):MySQL默認採用自動提交的模式。也就是說若是不是顯示地開始一個事務,則每一個查詢都會被當作一個事務執行提交操做。能夠經過設置AUTOCOMMIT變量來啓用或禁用

             自動提交模式。另外,有一些命令執行以前會強制執行COMMIT提交當前的活動事務。

         b. 隱式和顯示鎖定:事務執行過程當中,隨時均可以執行鎖定,鎖只有在執行COMMIT或者ROLLBACK的時候纔會釋放,而且全部的鎖是在同一時刻被釋放。這些都是隱式鎖。

7. MySQL的大多數事務型存儲引擎實現的都不是簡單的行級鎖。基於提高併發性能的考慮,它們通常都同時實現了多個版本併發控制(MVCC, Multi-Version Concurrency Control)。能夠認爲MVCC是行級鎖的一個變種,可是它在不少狀況下避免了

    加鎖操做,所以開銷更低。MVCC的實現,經過保存數據在某個時間點的快照來實現的。

8. 在文件系統中,MySQL將每一個數據庫(也能夠稱爲schema)保存爲數據目錄下的一個子目錄。建立表時,MySQL會在數據庫子目錄下建立一個和表同名的.frm文件保存表的定義。例如:MyTable表,對應

    MyTable.frm文件。

9. MySQL在5.5之後才完全使用InnoDB plugin替代舊版本的InnoDB。做爲事務型存儲引擎,InnoDB經過一些機制和工具支持真正的熱備份,Oracle提供的MySQL Enterpries Backup 、Percona提供開源的

    XtraBackup均可以作到這一點。MySQL的其餘存儲引擎不支持熱備份,要獲取一致性視圖須要中止對全部表的寫入,而在讀寫混合場景中,中止寫入可能也意味着中止讀取。

 

 

Schema與數據類型優化

1. 選擇優化的數據類型

    1). 更小的一般更好:更小的數據類型一般更快,由於他們佔用更少的磁盤、內存和CPU緩存,而且處理須要的CPU週期也更少。

    2). 簡單就好:簡單的數據類型的操做一般須要更少的CPU週期。例如:整型比字符串操做的代價更低,由於字符集和校對規則(排序規則)是字符串比較比整型比較更復雜。這裏有兩個例子:

                       一個是應該使用MySQL內建的類型而不是字符串來存儲日期和時間,另一個是應該使用整型存儲IP地址。

    3). 避免使用null:一般狀況下最好指定列爲not null,除非真的須要存儲null。由於null列使得索引、索引統計和值比較都更復雜。可爲null的列會使用更多的存儲空間,在MySQL中也須要特殊處理。

2. MySQL兼容性支持不少別名,例如INTEGER、BOOL等。他們都是別名,這些別名可能使人不解,但不會影響性能。若是建表時採用數據烈性的別名,而後用show create table檢查,會發現MySQL

    報告的是基本類型,而不是別名。

3. 整數類型:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分別使用8,16,24,32,64位存儲空間。它們的存儲值的範圍從-2的n-1次冪,到2的n-1次冪減一。

    1). 整數類型有可選的UNSIGNED屬性,表示不容許負值,這大體可使正數的上限提升一倍。

    2). 有符號和無符號類型使用相同的存儲空間,而且有相同的性能,所以能夠根據實際狀況選擇合適的類型。

    3). MySQL能夠爲正數類型指定寬度,例如INT(11),但大多數應用這是沒有意義的。對於存儲和計算來講,INT(1)和INT(20)是相同的。

4. 實數類型:實數是帶有小數部分的數字。然而,它們不僅是爲了存儲小數部分;也可使用DECIMAL存儲比BIGINT還大的整數。

    1). FLOAT和DOUBLE類型支持使用標準的浮點運算進行近視計算DECIMAL類型用於存儲精確的小數。

    2). 浮點類型在存儲一樣類型的範圍的值時,一般比DECIMAL使用更少的空間。FLOAT使用4個字節存儲.DOUBLE佔用8個字節,相比FLOAT有更高的精度和更大的範圍。

    3). 由於須要額外的空間和計算開銷,因此應該儘可能只在對小數進行精確計算時才使用DECIMAL。在數據量比較大的時候,能夠考慮使用BIGINT代替DECIMAL,將對應的值擴大N倍。

5. 字符串類型:

    1). VARCHAR:它比定長類型更節省空間,由於它僅使用必要的空間。VARCHAR節省了空間,因此對性能也有幫助。可是因爲行是變長的,在UPDATE時可能使行變得比原來更長,這就致使須要作額外的工做。

         下面的狀況使用VARCHAR是合適的:字符串最大長度比平均長度大不少;列的更新少,因此碎片不是問題;使用了像UTF-8這樣複雜的字符集,每一個字符使用不一樣的字節數。

         在5.0或更高的版本中,MySQL在存儲和檢索時會保留末尾空格。InnoDB則更靈活,它能夠把長的VARCHAR存儲爲BLOB。

    2). CHAR: 定長,當存儲CHAR值時,MySQL會刪除全部的末尾空格。定長的CHAR類型不容易產生碎片,對於很是短的列,CHAR比VARCHAR在存儲空間上也更有效率,VACHAR還有一個記錄長度的額外字節。

    3). 記住字符串的長度定義不是字節數,是字符數。多字節字符集會須要更多的空間存儲單個字符。

    4). 與CHAR和VARCHAR相似的類型還有BINARY和VARBINARY,它們存儲的是二進制字符串。二進制字符串中存儲的是字節碼而不是字符。

         二進制比較的優點並不只僅體如今大小寫敏感上。MySQL比較BINARY字符串是,每次按一個字節,而且根據該字節的數值進行比較。所以,二進制比字符比較簡單的多,因此也就更快。

    5). BLOB和TEXT類型:BLOB和TEXT都是爲了存儲很大的數據而設計的字符串數據類型,分別採用二進制和字符方式存儲。當BLOB和TEXT值太大時,InnoDB會使用專門的"外部"存儲區域來進行存儲。原表字段

          存儲指針指向外部存儲區域。

6. 日期和時間類型:MySQL能存儲的最小時間粒度爲秒。

    1). DATETIME : 這個類型能保存大範圍的值,從1001年到9999年,精度爲秒。它把日期和時間封裝到格式爲YYYYMMDDHHMMSS的整數中。默認顯示格式爲"2008-02-16 22:37:08"

    2). TIMESTAMP:保存從1970年1月1日午夜依賴的秒數,它和UNIX時間戳相同。只能表示從1970年到2038年。TIMESTAMP由於空間佔用小,因此效率更高。

    3). 可使用BIGINT類型存儲微秒級別的時間戳。

7. 位運算:BIT , SET 

8. 選擇標識符(identifier,主鍵) 

    1). 當選擇標識列的類型時,不只僅須要考慮存儲類型,還須要考慮MySQL這種類型怎麼執行計算和比較

    2). 一旦選擇了一種類型,要確保在全部關聯表中都使用一樣的類型。會用不一樣數據類型可能致使性能問題,即便沒有性能影響,在比較操做時隱式類型轉換也可能致使很難發現錯誤。

    3). 在能夠知足值的範圍要求,而且預留將來增加空間的前提下,應該選擇最小的數據類型。

    4). 整數類型一般是標識列最好的選擇,由於它們很快而且可使用AUTO_INCREMENT

    5). 若是可能,應該避免使用字符串類型做爲標識列,由於它們很消耗空間,而且一般比數字類型慢。

    6). 對於徹底"隨機"的字符串也須要多加註意。例如:MD5(),SHAI()或者UUID()產生的字符串。這些函數生成的新值也任意分佈在很大空間內,這會致使INSERT和一些SELECT語句很緩慢

    7).若是存儲UUID值,則應該移除"-"符號,或者更好的作法是,用UNHEX()函數轉換UUID值爲16字節的數字,並存儲在一個BINARY(16)的列中。檢索時再轉換回來。

9. 小心利用框架自動生成的schema(表)

10. 人們一般使用VARCHAR(15)來存儲IP地址。然而,它們實際是32位無符號整數,不是字符串。用小數點將字段分割成四段是爲了閱讀方便。因此應該用無符號整數存儲IP地址。MySQL提供INET_ATON()

      和INET_NTOA()函數在這兩種表示方法之間轉換。(inet_ntoa(3507806248)  --> 209.20.224.40 )

11. MySQL schema 設計中的陷阱:

      1). 太多的列

      2). 太多的關聯

      3). 全能的枚舉

      4). 變相的枚舉

      5). 非此發明的NULL:不要由於不使用NULL值,而走極端,根據實際狀況也可使用NULL

12. 範式的優勢和缺點

      優勢:

      1). 範式化的更新操做一般比反範式化要快

      2). 修改更少的數據

      3). 範式化的表一般表更小,能夠更好地放在內存中,因此執行操做會更快

      缺點:一般須要關聯查詢,不只代價昂貴,也可能使一些索引策略無效

13. 反範式的優勢和缺點:

      優勢:很好的避免關聯,更有效的使用索引策略

      缺點:範式的優勢,就是反範式的缺點

14. 緩存表和彙總表:

     1). 緩存表:存儲那些能夠比較容易的從schema其餘表獲取(但每次獲取速度緩慢)數據的表

     2). 彙總表:保存的是使用GROUP BY語句聚合數據的表。實時計算統計值是很昂貴的操做。

     4). 在使用緩存表和彙總表時,必須決定是實時維護數據仍是按期重建。哪一個更好依賴於應用程序,可是按期重建並不僅是節省資源,能夠保持表不會有不少碎片,以及徹底順序組織的索引。

15. 影子表:指的是在一張真實表"背後" 建立的表。當完成了建表操做後,能夠經過一個原子的重命名操做切換影子表和原表。原表儘可能保留備份,防止新表出問題。

16. 物化視圖:物化視圖其實是預先計算而且存儲在磁盤上的表,能夠經過各類各樣的策略刷新和更新。MySQL並不原聲支持物化視圖,可使用開源工具Flexviews。

                    對比傳統的維護彙總表和緩存表的方法,Flexviews經過提起對源表的更改,能夠增量地從新計算物化視圖的內容。

 17. 計數器表:建立一張獨立的表存儲計數器一般是一個好主意。使用計數器表的一些技巧

       1). 爲了防止互斥鎖影響效率,能夠添加多條記錄,隨機更新一條記錄。統計總數時,將全部數據相加。

       2). 對於須要根據時間更新計數器,也能夠用上述方法,不過多加一步操做。天天定時將前一天的總數合計起來,插入到計數器表,刪除那些零散的統計記錄。

18. 加快ALTER TABLE操做的速度:MySQL的ALTER TABLE操做的性能對大表來講是一個問題。MySQL執行大部分修改表結構的方法是用新的結構建立一個空表,從舊錶中查出全部數據插入新表,而後刪除舊錶。

      能夠經過ALTER COLUMN操做來改變列的默認值。這個語句會直接修改.frm文件而不涉及表數據。因此,這個操做很是快。

  

 

1. 更小的一般更好:更小的數據類型一般更快,由於他們佔用更少的磁盤、內存和CPU緩存,而且處理須要的CPU週期也更少。

2. 簡單就好:簡單的數據類型的操做一般須要更少的CPU週期。例如:整型比字符串操做的代價更低,由於字符集和校對規則(排序規則)是字符串比較比整型比較更復雜。這裏有兩個例子:

                   一個是應該使用MySQL內建的類型而不是字符串來存儲日期和時間,另一個是應該使用整型存儲IP地址。

3. 避免使用null:一般狀況下最好指定列爲not null,除非真的須要存儲null。由於null列使得索引、索引統計和值比較都更復雜。可爲null的列會使用更多的存儲空間,在MySQL中也須要特殊處理。

4. 由於須要額外的空間和計算開銷,因此應該儘可能只在對小數進行精確計算時才使用DECIMAL。在數據量比較大的時候,能夠考慮使用BIGINT代替DECIMAL,將對應的值擴大N倍。

5. 二進制比較的優點並不只僅體如今大小寫敏感上。MySQL比較BINARY字符串是,每次按一個字節,而且根據該字節的數值進行比較。所以,二進制比字符比較簡單的多,因此也就更快。

6. 可使用BIGINT類型存儲微秒級別的時間戳。

7. 一旦選擇了一種類型,要確保在全部關聯表中都使用一樣的類型。會用不一樣數據類型可能致使性能問題,即便沒有性能影響,在比較操做時隱式類型轉換也可能致使很難發現錯誤。

8. 若是可能,應該避免使用字符串類型做爲標識列,由於它們很消耗空間,而且一般比數字類型慢。

9. 範式(修改多,關聯查詢少)和反範式(查詢多,修改少)的選擇

10. 緩存表和彙總表

相關文章
相關標籤/搜索