大表带来的问题
下面我們來看看除了上面講的因素之外,還有什么會對數據庫的性能,造成影響,首先第一點大表會給我們帶來的問題,另外就是大事務會給我們帶來什么樣的影響,那什么樣的表稱之為大表呢,其實大表就是相對而言的,對于不同的存儲引擎,會有不同的限制,以目前InnoDB的版本而言呢,并沒有定義說每個表的最大行數是多少,只要存儲空間允許,我們就可以把數據放到MYSQL的表中,關于MSYQL存儲引擎呢,在下面還會有詳細的介紹,但是在實際使用過程中呢,我們會發現,當一個表的數據量超過千萬行的時候,就會對數據庫的性能造成影響,這里說的大表呢就可以通過維度來進行定義,一個是一個表的記錄超過一千萬行,而另一個呢,一個表的數據超過10個G,當然這個定義是相對的,要和我們的具體業務場景和磁盤IO情況而定,如果我們這個表只是用來記錄日志的,只有insert操作和select操作,而幾乎沒有update和delete操作的話,這樣的表就算是超過1千萬行,對我們的業務也不會有什么影響,但是也是有例外的情況的,之前我們就遇見過這樣的一張表,表中的記錄差不多10個億了,但是工作的一直很穩定,因為很少有人去關注他,只是用于記錄一些操作日志,當有一天業務出現變更,日志表插入更多的列,這時會發現,雖然一張表增加列,就會是一種十分痛苦的事情,當數據被同步到了N個服務器上的時候,那就可以說是災難了,另外一個大表的定義,數據庫文件超過10個G,這時對于普通的磁盤來說,如果我們使用的是高端磁盤的話,性能可能就會大一些,那么我們看看大表會帶來什么樣的問題
首先大表會對查詢造成了影響,大表往往就意味著慢查詢的產生,前面提高了CPU的處理的效率呢,對于數據庫的性能是至關重要的,而代表往往會降低CPU的處理效率,以這張訂單來源日志記錄的表來說吧,在這個表中呢,記錄了訂單的來源日志,其中訂單來源由order_from,這個字段來記錄,一共有4中來源,一個是來源于公司的網站,也就是我們的web,另外就是來源于京東,或者淘寶的第三方平臺,剛才說過,之前的公司在國內電商中呢,算是很不錯的了,所以訂單表有上億條記錄了,由于之前沒有需求對這個表進行查詢,所以也一直沒有發生什么問題
知道有一天運營要查看一下京東渠道來源的訂單量,這就一下產生大量的問題,渠道只有4個,區分度是很低的,所以要在一個上億條的表中,篩選出一部分的數據,就要使用大量的磁盤IO,然后磁盤的效率也會很低,再進一步來擴展這個問題,如果我們要在頁面上顯示某一個商品從不同渠道來源的訂單固定用戶的購買,那么這個查詢就會在每次,用戶訪問商品時,都會執行,這樣就產生了大量的慢查詢,之所以這樣說呢
這就是我之前所遇到過的一個案例,當時就在網頁顯示各個分類,就是銷量的排行,就把整個數據庫就給搞死了,然后這種SQL都是有辦法優化的,之后我們也會降到這種查詢的優化方式,咱們在這里只是給大家一個印象,就是我們的大表,會給我們帶來的一個影響,還有大表對在DDL數據定義操作也會造成影響,首先來說,大表對于DDL的第一個影響,我們在大表上建立索引,這個就需要很長的時間,這個會給我們帶來什么樣的風險呢,當MYSQL5.5之前的版本中,我們使用MSYQL的InnoDB的話,對于建立索引的操作,實際上是會鎖表的,而對于5.5以后的版本,雖然建立索引不會鎖表,通常會引起長時間的主從延遲,也會影響正常的業務,所以要在大表上建立索引,我們一定要非常的小心,在下面的內容中呢,會具體的談到,如果在大表中建立索引,希望提供一些幫助
修改表結構是需要長時間鎖表的,有什么樣的風險呢,首先會造成長時間的主從延遲,這就和建立索引一樣了,由于咱們目前MYSQL的主從這種機制,對于所有的DDL操作,在主庫上完成之后,然后到從庫上,然后再到從庫上進行相同的操作,這樣來完成對表結構的復制的,假設我們一張表在主庫上,進行修改需要80秒的時間,一個表結構的修改,那么在從服務器上呢,至少也需要80秒來進行修改,因為目前MYSQL的主從復制呢,都是使用單線程,所以一旦有大量的修改,而從服務器上沒有完成,其他的數據庫操作都無法執行,這樣就至少造成480秒以上的主從延遲,這對于大多數應用來說呢,都是無法接受的,雖然在MYSQL5.6版本中呢,支持多線程的復制,但是也會有一定的限制,這個我們后面再說,2014年我所在的這個公司,所使用的MYSQL呢,是5.5的版本,所以對這種大表的操作呢,成了一個很棘手的問題,對大表DDL的第二個風險呢,在這種主庫上進行表結構修改的時候呢,這個表所有操作都會被阻塞,這樣就會影響正常的數據庫操作,如果一個表的訪問會很頻繁,就像訂單來源日志表,我們每一個訂單都會往里面插入,如果我們這個時候對于訂單來源日志表進行修改,比如說增加字段,修改某個字段的長度,在剛才的MYSQL版本中呢,修改都是要進行多表的,那么這個時候呢,如果你要對大的表進行修改呢,你會遇到一個非常棘手的問題,你的數據庫的連接數呢,會猛增,這個是什么原因呢,因為我們連接都被阻塞掉了,因為我們在修改這個表結構,因為所有的修改操作呢,要等表結構修改完成之后,我們再繼續,從前面我們就說過了,數據庫連接數被占滿了呢,就會出現500錯誤,這個時候你的老板就得對你大吼了,雖然大表對我們的數據庫有這么大的影響,那么我們就簡單看一下如何解決大表的問題
首先對大表的處理方式主要有兩種,一種就是咱們聽說的分庫分表,之所以說是傳說的分庫分表,相信很少有人公司實際上做過分庫分表的操作,要進行分庫分表呢,首先要解決兩個難點,一個是分表關鍵鍵的選擇,這個往往要根據業務的不同,可以有多種分表的方式,比如對于訂單表來說,我們可以以訂單號來分表,也可以按地區來分表,所以選擇合適的分表鍵,我們的后續的業務是十分重要的,另一個難點就是分表之后,跨分區的數據庫查詢這個問題如何解決,大家不要認為選擇了好的主鍵之后,就不需要跨分區查詢了,好的分區鍵只能更好的查詢,但是這種跨分區查詢還是會發生的,當然還會有其他的問題要解決,這個我們下節內容會詳細講到來給數據庫分庫分表,我有幸做過分庫分表的一個優化,就是在14年大促之后的事情了,為了解決訂單表和訂單明細表過大的問題,公司決定,把訂單相關表進行分庫分表操作,當時是調用了大量的人力和物力,來進行這個項目,耗時將近兩個月完成了,分庫分表操作,因為下一次公司大促之前上線,但是效果還是不錯的,但是其中還是出現很多問題,特別是分庫分表后使用原有的訂單,相關的統計報表,這樣的后天操作功能,合并到一臺服務器上,作為后臺統計和管理所使用的數據庫,下面的章節中我會詳細的介紹到,我們分庫分表的項目,如果從上面的介紹呢,大家也可以看出來,分庫分表操作呢,需要消耗大量的人力和物力的,同時還要冒著影響先有后端業務的風險,所以呢我個人認為,分庫分表并不是適合所有公司適合的,其實在大多數情況下,我們要選擇另外一種方式來對大表進行一種處理
另外一種處理方式就是對大表進行一種歷史數據歸檔了,特別是對于日志記錄的大表呢,像訂單這種業務表呢,我們也可以進行歸檔,減少對前后端業務的影響,因為對于前端業務來說呢,實際上表結構并沒有什么變化,所以一切的程序都會正常的使用,而只是對于訂單表這樣的業務表,我們要進行歸檔,就要增加一個歷史查詢的入口,可以說已經歸檔的歷史訂單呢,很少有人會進行查詢的,所以就算歸檔表很大,對業務的影響也是很輕微的,而歸檔表和正常使用的表可以放在不同的服務器上,這樣一方面減少了業務數據,這樣一方面減少了熱數據在服務器上的容量,減少核心服務器的查詢壓力,而對于后端業務來說呢,已經完成相關操作后統計的歷史數據,所以對后端的應用不會有什么影響,但是為了完成不影響前后端,現有的業務邏輯呢,我們對數據進行歸檔時,兩個難點,其一呢是歸檔時間點的選擇,都是已經不會被使用,或者是很少使用的數據,所以歸檔時間點呢,比如訂單列表我們可以選擇幾年前的數據,你也可以選擇歸檔一個月的數據,那么從這里看呢,對于訂單列表來說,歸檔一年前的數據可能更加合適,而一個月的數據我們就歸檔一個月的數據就OK了,進行歸檔數據的第二個難點呢就是如何進行歸檔操作,對于大表的增刪改查,要十分的小心,如果我們要進行歸檔,要把已經歸檔的歷史數據呢,從私有的表中進行刪除,那如果我們對于上億的表的數據分成幾十萬,不然會輕易的產生主從的延遲,重則就會大量的阻塞,影響咱們正常的業務訪問,對于如何進行大表的增刪改查,我們在下面同樣會有詳細的說明
?
總結
- 上一篇: 在大促中什么影响了数据库性能
- 下一篇: 大事务带来的问题