你們在面試的時候,是否遭遇過,面試官詢問mysql
大家是如何進行數據庫優化的?面試
那這個問題應該怎麼答呢?其實寫這個題材的緣由是我這幾天看到各公衆號轉的一篇數據庫調優的知識(不上連接了),我就稍微翻了幾下,上面動不動就來講要對數據庫進行水平拆分,我就想反問各位讀者,大家幾我的經歷過水平拆分?如今不少文章,實踐性實在太差,只能說純理論分析。
這篇文章最先來自知乎的一個提問,我在其基礎上完善了一下。redis
這纔是調優的第一階段啊,爲何呢?
由於這一步成本最低啊,不須要加什麼中間件。你沒通過索引優化和SQL優化,就來什麼水平拆分,這不是坑人麼。
那步驟是什麼樣呢?我說個大概
(1)用慢查詢日誌定位執行效率低的SQL
語句
(2)用explain
分析SQL
的執行計劃
(3)肯定問題,採起相應的優化措施,創建索引啊,等
我就不舉例了,由於如何優化SQL的文章,一抓一大把,再貼過來,讀者看着也累。sql
在優化sql沒法解決問題的狀況下,才考慮搭建緩存。畢竟你使用緩存的目的,就是將複雜的、耗時的、不常變的執行結果緩存起來,下降數據庫的資源消耗。
這裏須要注意的是:搭建緩存後,系統的複雜性增長了。你須要考慮不少問題,好比:數據庫
緩存也搞不定的狀況下,搞主從複製,上讀寫分離。在應用層,區分讀寫請求。或者利用現成的中間件mycat或者altas等作讀寫分離。
須要注意的是,只要你敢說你用了主從架構,有三個問題,你要準備:
(1)主從的好處?
回答:實現數據庫備份,實現數據庫負載均衡,提交數據庫可用性
(2)主從的原理?
回答:如圖所示(圖片不是本身畫的,偷懶了)
主庫有一個log dump
線程,將binlog
傳給從庫
從庫有兩個線程,一個I/O線程,一個SQL線程,I/O線程讀取主庫傳過來的binlog
內容並寫入到relay log
,SQL線程從relay log
裏面讀取內容,寫入從庫的數據庫。緩存
(3)如何解決主從一致性?
回答:這個問題,我不建議在數據庫層面解決該問題。根據CAP定理,主從架構原本就是一種高可用架構,是沒法知足一致性的
哪怕你採用同步複製模式或者半同步複製模式,都是弱一致性,並非強一致性。因此,推薦仍是利用緩存,來解決該問題。
步驟以下:
一、本身經過測試,計算主從延遲時間,建議mysql版本爲5.7之後,由於mysql自5.7開始,多線程複製功能比較完善,通常能保證延遲在1s內。不過話說回來,mysql如今都出到8.x了,還有人用5.x的版本麼。
二、數據庫的寫操做,先寫數據庫,再寫cache,可是有效期很短,就比主從延時的時間稍微長一點。
三、讀請求的時候,先讀緩存,緩存不存在(這時主從同步已經完成),再讀數據庫。多線程
說句實在話,大家面試的時候,其實能夠略過這個階段。由於不少互聯網公司都不建議用分區表,我本身也不太建議用分區表,採用這個分區表,坑太多。
這裏引用一下其餘文章的回答:
什麼是mysql的分區表?
回答:全部數據還在一個表中,但物理存儲根據必定的規則放在不一樣的文件中。這個是mysql支持的功能,業務代碼不須要改動,可是sql語句須要改動,sql條件須要帶上分區的列。
缺點
(1)分區鍵設計不太靈活,若是不走分區鍵,很容易出現全表鎖
(2)在分區表使用ALTER TABLE
… ORDER BY
,只能在每一個分區內進行order by
。
(3)分區表的分區鍵建立索引,那麼這個索引也將被分區。分區鍵沒有全局索引一說。
(4)本身分庫分表,本身掌控業務場景與訪問模式,可控。分區表,研發寫了一個sql,都不肯定該去哪一個分區查,不太可控。
...不列舉了,不推薦架構
上面四個階段都沒搞定,就來垂直拆分了。垂直拆分的複雜度仍是比水平拆分小的。將你的表,按模塊拆分爲不一樣的小表。你們應該都看過《大型網站架構演變之路》,這種類型的文章或者書籍,基本都有提到這一階段。
若是你有幸可以在什麼運營商、銀行等公司上班,你會發現他們一個表,幾百個字段都是很常見的事情。因此,應該要進行拆分,拆分原則通常是以下三點:
(1)把不經常使用的字段單獨放在一張表。
(2)把經常使用的字段單獨放一張表
(3)常常組合查詢的列放在一張表中(聯合索引)。負載均衡
OK,水平拆分是最麻煩的一個階段,拆分後會有不少的問題,我再強調一次,水平拆分必定是最最最最後的選擇。從某種意義上,我以爲還不如垂直拆分。由於你用垂直拆分,分紅不一樣模塊後,發現單模塊的壓力過大,你徹底能夠給該模塊單獨作優化,例如提升該模塊的機器配置等。若是是水平拆分,拆成兩張表,代碼須要變更,而後發現兩張表還不行,再變代碼,再拆成三張表的?水平拆分模塊間耦合性太強,成本太大,不是特別推薦。