Mysql優化相關總結

Mysql優化相關總結

2016-05-31 數據庫集中營

優化順序:mysql

  • 選擇適當的引擎和表結構和數據類型redis

  • 創建索引,優化sql。sql

  • 增長緩存,redis、memcache。數據庫

  • 主從、主主,讀寫分離。緩存

  • mysql自帶分區表架構

  • 根據業務耦合垂直拆分,分佈式數據庫併發

  • 水平拆分,選擇合理的sharding key。分佈式

引擎區別與選擇:函數

  • Innodb採用聚簇索引,聚簇索引包含data。輔助索引(複合索引、前綴索引、惟一索引)存儲的是主索引的值,因此查找時須要兩次B-Tree搜索,讀的效率稍低。可是覆蓋索引和自適應的哈希索引能夠必定程度上緩解這個問題(自適應哈希索引不須要用戶指定,Innodb在運行時動態的根據距離的訪問頻率和模式爲一部分頁創建哈希索引,但只存在內存中,停庫會丟失,重啓後慢慢從新維護)。Innodb使用的是行鎖,粒度更小,併發更強。而且讀寫之間是能夠併發的,讀不須要加鎖,根據隔離級別不一樣,遇到鎖時讀取快照。因此讀寫併發是很好的。另外,Innodb相比MyIsam提供事務和外鍵功能。post

  • MyIsam數據和索引是分開存儲的,索引緩存在內存中,索引存儲的是數據的磁盤地址。因此不須要屢次查詢B-Tree,讀的性能好。可是MyIsam是表鎖,只有讀讀之間是併發的,所以寫的效率差。而且寫優先級高,大量寫可能致使操做餓死。

  • 綜上所述:若是應用的讀寫操做比例很是大,或須要全文索引,那麼可使用MyIsam(5.6開始Innodb也支持全文索引)。其餘狀況,除了特殊狀況特殊分析,推薦Innodb。

 

數據類型的選擇:

  • char、varchar:char是固定長度的,varchar是可變長度的,因此char的處理速度要快得多。char適合長度變化不大的數據列,或要求查詢速度很嚴苛的場景。Myisam建議用char,Innodb建議用varchar。

  • text、blob:blob能夠存二進制,text只能存字符數據。能夠經過合成索引來提升大文本字段的檢索性能(創建一個額外的列存儲大文本列數據的散列值),但這種方法只適用於精確完整的匹配查詢。前綴索引也有助於查詢,但查詢條件不能以%開頭。

  • 浮點數、定點數:float、double是浮點數,精度超出時會四捨五入。decimal、numberic是定點數,實際使用字符串存儲的,因此精度更高,超出精度會警告或直接報錯。因此:貨幣等精度敏感的數據要用定點數,由於浮點數存在偏差問題。

  • 日期類型:DATETIME能存儲年月日時分秒,比TIMESTAMP能表示的年份更久遠。若是涉及時區問題,用TIMESTAMP。


字符集: 

  • 不一樣的字符集可能涉及隱式的轉換,而致使索引失效。

表結構:

  • 選擇合適的主鍵(選擇性,長短),不要寬表,不要太多關聯,不要大字段。

  • 關於範式:

    • 第一,一個字段只存一個意義的值。{學號,性別+年齡} 。解決辦法:{學號,性別,年齡}

    • 第二,若是主鍵是複合主鍵,非主鍵字段不能依賴主鍵的一部分,必須依賴所有。{學號,學科,分數,總分},分數依賴複合主鍵,可是總分只依賴學科一個字段,因此不符合第二範式。解決辦法:{學號,學科,分數} {學科,總分}

    • 第三,不能有冗餘。{學號,班級,班主任}班主任字段就會有大量冗餘。解決辦法:({學號,班級} {班級,班主任})

    • 範式不必定要嚴格遵照,要根據具體狀況抉擇,適當的違反有時候會帶來好處更多一些。例如,

  • qq的用戶表存儲qq圖標的點亮狀況,若是每一個圖標用一個字段存儲,那麼幾十個圖標會使表很寬、很浪費空間。若是用位圖存儲全部的點亮狀況,一個或者兩個字段就能夠。雖然違反了第一範式,可是依然是個好辦法。

  • 第2、第三範式雖然保證了表的嚴謹,可是可能帶來更多的鏈接。適當違反能夠減小鏈接,特別是當分佈式部署時,會省去不少麻煩。

 

索引的設計和使用:

  • Myisam和Innodb的索引都是BTree索引,B表明平衡樹。都支持前綴索引,前綴索引有個缺點:order by和group by不能使用該索引。Myisam支持全文索引(5.6開始innodb也支持全文索引)。

  • 最適合作索引的列是出如今where子句和連接子句中的列,而不是select中的。

  • 索引列要使用短列,若是長字符列作索引,儘可能用前綴索引,在最短的長度內,知足足夠的選擇性。

  • 不要過分索引,給插入和更新帶來很大負擔。

  • Innodb儘可能用自增列作主索引,若是不能,也不要用大字段。

  • 最左前綴原則是BTree索引使用的首要原則,即索引條件中列的順序,按複合索引中列的順序,從左到右儘可能覆蓋,中間不能間斷,且儘可能以精確的「=」爲條件。從左到右第一個使用範圍比較的條件可使用索引,但後面的條件列再也不能使用索引。

  • 常見不能使用索引的場景:

    • 以%開頭的Like查詢。能夠考慮用全文索引。或利用Innodb的聚簇索引,掃索引比掃錶快得多。例如:一個表有主鍵id,輔助索引name。如今想根據name模糊搜索 name like %end%,直接select * from table where name like %end%,會引發表的全掃描,效率低下。由於Innodb每一個輔助索引中存的都是主鍵的值,因此能夠改成select * from (select id from table where name like %end%) a, table b where a.id = b.id;  這樣子查詢中由於id和name在輔助索引中知足了覆蓋索引,只掃索引就能夠拿到全部知足條件的id,而後根據id再去查詢最終結果。

    • 出現類型轉換、函數、運算、轉碼時。

    • 不包含複合索引左側列。

    • mysql猜想掃表比使用索引快的時候。

    • or鏈接的條件中,每一個字段必須都能用到索引,不然將全不使用索引。

事務和鎖:

  • Innodb提供事務功能,Myisam不提供。

  • Innodb採用行級鎖,也支持表級鎖。Myisam提供表級鎖。Innodb的讀寫併發性更好,但行級鎖有出現死鎖的可能。

  • Innodb的行級鎖是對索引項加鎖實現的,意味着不經過索引檢索就會鎖定全部記錄,與表鎖相同。行鎖分爲三種:

    • record lock:索引項加鎖

    • gap lock:間隙鎖

    • Next-key lock:前面兩個的組合

  • 事務:

    • 未提交讀 read uncommit

    • 已提交讀 read commit : 解決髒讀

    • 可重複讀 repeatable read : 解決不可重複讀 (默認級別)

    • 可序列化 serializable : 解決幻讀

    • 更新丟失

    • 髒讀

    • 不可重複讀

    • 幻讀

    • 原子性、一致性、持久性、隔離性

    • 併發事務處理能提升效率和資源利用率,可是也帶來了問題:

    • 隔離級別:髒讀、不可重複讀、幻讀都是一致性問題,須要隔離機制來解決。隔離機制有兩種:加鎖、生成一致性快照。事務隔離越嚴格,反作用越小,代價越大。現有4個隔離級別,能夠根據業務不一樣進行選擇:

    • 默認的隔離界別可重複讀,會出現幻讀的問題。select...for update能夠解決幻讀問題。eg:select * from data where id < 100 fro update;  會鎖定id小於100的全部記錄以及不存在的記錄」間隙「也加鎖,也級是next-key lock,因此就避免了幻讀。但容易形成嚴重的鎖等待,儘可能不用,而用精確等於的條件訪問更新數據。值得說明的是,當用等於條件來請求一個不存在的數據時,也會加next-key lock。

  • 死鎖預防:

    • 以相同順序訪問表

    • 事務中,若是須要更新記錄,應該直接申請足夠級別的鎖:排它鎖。

    •  

  • 分佈式事務:5.0.3開始支持,且只有Innodb。兩段式提交,可是效率不理想。

表的拆分:

  • 垂直拆分:主碼和一部分列放在一個表, 主碼和另外一部分放在另一個表。好處是行更小,數據頁能放更多緩存,壞處是須要管理冗餘,獲取所有數據須要join。

  • 水平拆分:當表很大或表中數據原本就具備獨立性時。優勢:下降索引層數,缺點:給應用帶來複雜性。

 

分區表:

  • 把一個表分紅多個小的部分,對應用來講是透明的。能夠存儲更多的數據,提升查詢吞吐量。where字句包含分區條件時,能夠只掃描部分分區,提升效率。sum、count等操做,能夠在分區上並行進行再彙總。

  • 同一個表的全部分區必須相同引擎。

  • 分區類型:RANGE 範圍,LIST 根據枚舉,HASH 散列,KEY 相似hash。不能使用主鍵、惟一鍵之外的字段作分區字段。

優化手段:

  • 經過慢查詢日誌查看已經執行的慢語句記錄。show processlist查看當前mysql正在運行的線程。

  • EXPLAIN查看慢sql的執行計劃。

    • ALL:全表掃描

    • index:索引全掃描

    • range:索引範圍掃描

    • ref:使用非惟一索引或惟一索引的前綴索引

    • eq-ref:使用惟一索引

    • const   system : 單表只有最多一個匹配行,能夠很是迅速的找到。

    • NULL:不須要訪問表或者索引。

    • select_type:select的類型。SIMPLE 簡單表、PRIMARY 主查詢、UNION 聯合中第二個或後面的、SUBQUERY子查詢。

    • table:表名

    • type:在表中找到所需行的方式。效率從低到高:

    • possible_keys:可能使用的索引

    • keys:實際使用的索引

    • key_len:使用到的索引字段的長度

    • rows:掃描行的數量

    • Extra:額外的信息

  • explain extended 加上show warnings可以看到sql真正執行前,優化器作了哪些修改。

  • show profiles能夠查看當前線程每一個查詢。show profile for query + id(show profiles獲得的),能夠看每一步的耗時。還能夠進一步在cpu io block等級別查看在使用什麼資源時,耗時高。例如:show profile cpu for query + id。

  • 5.6提供了trace對sql進行跟蹤,進一步瞭解優化器選擇最終執行計劃的緣由。

    • 首先打開trace:set optimizer_trace="enabled=on",END_MARKERS_IN_JSON=on;

    • 緩存大小:set  optimizer_trace_max_mem_size=1000000;

    • 執行sql

    • select * from information_schema.optimizer_trace; 查看跟蹤文件。

 

sql語句優化:

  • insert:若是單個客戶端插入多條,儘可能insert into test values(1,2),(3,4),(5,6)如此同時插入,減小交互

  • order by:btree索引是有序存儲的,能夠利用。因此儘可能減小額外的filesort,經過索引直接返回有序數據。作法:order by與where使用相同的索引、複合索引。而且order by的字段都是升序或都是降序。 若是作不到,排序操做不少,數據較多時,適當開大sort_buffer_size讓排序儘可能在內存中完成,這個值是每一個線程獨佔的,多個線程就多個buffer,注意!

  • group by:默認狀況下group by c1, c2會對c1,c2...的全部字段排序,若是不須要刻意經過顯示的加一個order by null禁止排序,提升效率。

  • 嵌套查詢:有些狀況可使用鏈接代替。

  • or:保證每一個列都能用到索引,會發現mysql處理時,將每一個字段分別查詢後進行了UNION操做。

  • 分頁查詢:limit1000,10 會排序出前1010行,最後只去10行。效率低。

    • 利用覆蓋索引:子查詢先利用覆蓋索引查詢到知足條件的主鍵,再利用主鍵回表查找記錄。eg:select name, value from data order by name limit 1000, 10; 改成 select name, value from data a inner join (select id from data order by name limit 1000, 10) b on a.id = b.id;

    • 紀錄上一次結果的最後一個排序列的值,而後:where name > lastvalue order by name limit 10; 這種方法不適合排序字段有重複值的狀況,會丟紀錄。

  • SQL提示:

    • USE INDEX : 讓mysql參考提供的索引。eg:select * from data use index (idx_id);

    • IGNORE INDEX:忽略某索引

    • FORCE INDEX:強制使用某索引

  • 對大表的統計操做:新建臨時表,講所需數據導入臨時表,再統計。好處:隔離,能夠臨時加字段、索引。

  • in not in  exist  not exist:    

  • 技巧:

    • order by rand() limit 5;隨機選出5行。

應用優化:

  • 鏈接創建的代價較大,應用鏈接池。

  • 若是表更新操做不頻繁,能夠利用查詢緩存。一旦表發生一點更新,整個表的緩存都將失效。

  • 增長cache層。

  • 主歷來分攤讀寫壓力,可是存在延遲,需考慮。

  • 分佈式數據庫CLUSTER。

 

 

其餘優化:

  • 按期分析表:analyze table test; 分析表可使系統獲得準確的統計信息,sql能生成更正確的執行計劃。

  • 優化表:optimize table test;合併空間碎片。

  • 上述兩個操做會鎖表!!!

 

集羣:

  • Mysql Cluster :

    •  節點類型:管理節點(1個)、SQL節點(應用和數據節點間的橋樑)、數據節點(存放數據,有多個鏡像節點應對宕機)

  • MMM架構:

    • 雙主複製架構,只有一個主提供寫,另外一個提供一部分讀。

  • MHA架構:

    • 兩部分組成:MHA Manager管理節點、MHA 

相關文章
相關標籤/搜索