03.01 mysql表數據量太大,達到了1億多條數據,除了分庫分表之外,還有沒有其他的解決方式?

韋德俊


軟件設計表數據量太大這個是架構設計裡,常遇到的問題。


先考慮優化,讀寫分離、合理索引、緩存數據、高頻讀取寫進redis等產品,也可以買非常多的實例來做負載,不過這些操作撐不了多久。 分庫分表幾乎是唯一的,也是最好的辦法。


當然分庫分表大家不願意操作,主要還是因為要改動業務代碼,還有一種傻瓜式操作,不需要你改業務代碼,那就是分區,例如你把數據一個月分一個區,數據庫 mysql 單表數據量達到千萬、億級,可以通過分表與表分區提升服務性能。


不過你說不想分庫分表,那就拿錢抗啊,上商業數據庫,Oracle、DB2、PGSQL等,即使上這些數據庫,你遲早還是得根據業務分庫分表,這個你可以問下頭條,淘寶,知乎這些大量數據的工程師,長期下去分庫,分表是唯一出入。


你看京東,淘寶你的訂單數據就知道了,默認顯示三個月, 有可能他們就是定義最近三個月為熱數據,當前常用庫,之前你的訂單在歷史數據庫裡面。這樣的好處,顯而易見的,你的系統查詢速度最大的影響因素,就是數據量。


這就像一個箱子裡面裝了100人,只能從上面往下面看找人, 如果你有1000人,做成10層的箱子, 要去箱子裡面找出5個穿紅色衣服的人很慢。 如果分成10個箱子,即使查找10次,也比在一個箱子裡面快。


架構裡面雖然沒有什麼唯一的解決辦法,遇到大數據,思路基本都是統一的,減少源站數據庫訪問,分庫分表。


神奇的老狼


通常來說,Mysql表的數據量達到一兩千萬之後,操作起來開始有些吃力了,如果數據量達到上億,估計系統是吃不消的。

那麼解決方案有哪些呢?我提幾個思路:

就用Mysql,不考慮遷移

  • 分庫分表其實是比較好的方案,但是已經被題主否了,就不詳細說了;

  • 表設計的優化:在設計表的時候,就要考慮性能問題了。例如字段儘量避免NULL,時間類型儘量使用TIMESTAMP,單表的字段不宜過多等等。

  • 索引的優化:索引不是越多越好,也不是所有的字段都適合建立索引,使用多列索引的時候,要注意SQL中的條件順序等。

  • SQL的優化:有的時候查詢慢,可能是SQL寫的爛。查詢儘量用到索引,避免錯誤的寫法導致索引失效,避免使用select *查詢出來所有的列,拆分複雜的SQL語句,查詢使用分頁等等。

  • 分區:分區表是獨立的邏輯表,底層由多個物理表組成,這些對用戶來說是透明的;如果按照分區字段查詢數據的話,就會在某一張分區表內查詢,速度回比較快;分區字段的選擇,需要根據你們實際業務來;比如你們這張表如果可以分100個分區的話,那麼每張表實際只有100萬的數據;使用分區表儘量避免全表掃描;建議考慮這種優化方式。

拋棄Mysql,遷移數據庫

  • 如果公司有錢的話,可以直接上商業數據庫,Oracle、DB2什麼的,一億的數據還是可以搞的定的,當然會也比較貴。

  • 其他開源數據庫,有可以支持千萬級的產品,不過不建議使用,坑會比較多。

  • 雲數據庫,可以考慮把數據遷移到雲上,比如阿里雲,花一些錢,少操一些;不過如果是比較敏感的數據,放到雲上,多少會不太放心;私有云?這個也貴。


另外,如果不遷移Mysql的話,可以加以非關係型數據庫進行輔助,例如一些數據放到Redis裡面進行緩存,或者通過跑數的方式,把原始數據加工好放到Mongodb中提供查詢,總之就是減少對數據庫的訪問。

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


會點代碼的大叔


mysql在常規配置下,一般只能承受2000萬的數據量(同時讀寫,且表中有大文本字段,單臺服務器)。現在超過1億,並不斷增加的情況下,建議如下處理:

1 分表。可以按時間,或按一定的規則拆分,做到查詢某一條數據庫,儘量在一個子表中即可。這是最有效的方法

2 讀寫分離。尤其是寫入,放在新表中,定期進行同步。如果其中記錄不斷有update,最好將寫的數據放在 redis中,定期同步

3 表的大文本字段分離出來,成為獨立的新表。大文本字段,可以使用NOSQL數據庫

4 優化架構,或優化SQL查詢,避免聯表查詢,儘量不要用count(*), in,遞歸等消耗性能的語句

5 用內存緩存,或在前端讀的時候,增加緩存數據庫。重複讀取時,直接從緩存中讀取。

上面是低成本的管理方法,基本幾臺服務器即可搞定,但是管理起來麻煩一些。


當然,如果整體數據量特別大的話,也不在乎投入費用的話,用集群吧,用TIDB吧


Paul梅斯


你不想分,就堆硬件堆帶寬唄。

單表數據上億可以採用以下方法

首先分表是必須的,然後分庫。

分表可以採用按時間分,根據實際情況一個月或一個季度的分。

網站前端列表採用只查詢最新表

另外是按分類分,如果數據還是大則在分類基礎上再時間拆分。

然後配合緩存,再不需要及時更新的頁面所有查詢都只從緩存中查詢。

這時候還慢的話,就再分庫

分庫最簡單的就是讀者分離,兩臺數據庫服務器。

如果讀者分離還慢,就考慮再加多臺讀服務器。

程序上不想改動就採用負載均衡分攤壓力。

但是這樣還有個問題就是,每臺服務器都要保存一樣的數據,及時同步,數據量大維護挺麻煩。

所以就得再業務層分庫了

最簡單的就是按地區分庫,訪問量高的地區都單獨使用服務器,只保存當前地區的數據,同時該地區數據也可以再分表,分庫。

業務層要做的就是在訪問入口判斷用戶所在地區,然後訪問當前地區數據庫。像58同城這種帶地區分站的網站都是這種策略。

一般大網站都是數據庫分佈式,緩存分佈式,模塊單獨部署,負載均衡,多節點,多種技術結合在一起的。

不過一億數據,分表和讀者分離,緩存就解決了。

負載均衡

緩存


小小CTO


mysql單表數據達1億,如果字段少,查詢維度單一,查詢字段有索引,查詢效率還是可以的;

如果字段較多,查詢維度多的話,可以參考如下方案:

1、數據歸檔

根據時間歸檔,比如將一年前的數據歸檔至歷史表

2、利用搜索引擎

將數據保存至solr或elasticsearch中


為夢想衝刺


在做垂直拆分或者水平擴展的時候,要大概清楚2億條數據庫是都經常性進行大規模的查詢還是更新?這決定了你擴展的思路,如果是範範的進行擴展,有時候會起到適得其反的效果。

1.首先要檢查哪些經常查詢的SQL是否可以有優化的地方,檢查數據庫的索引建立的是否合理,索引是否有效,可以嘗試建立分區表等,這一步主要是單個數據庫的優化。

2.在mysql的擴展上包括垂直拆分,即分庫分表的,這種需求需要在代碼層實現,需要開發人員在代碼層進行一些配置。這個可以起到寫的負載均衡。而水平擴展說白一點就是增加服務器的個數,由原來的一臺變成幾臺,再通過mysql的中間件,比如proxysql或者mycat進行一些配置(推薦proxysql),把寫請求放在那些性能好的服務器上,把讀分散到不同的服務器上,這樣就起到了讀的負載均衡。

3.如果上面垂直拆分或者水平擴展還是不能解決問題,可以考慮使用nosql,在前端增加一個緩存,memory cache或者redis來增加緩存,應用層在首先會讀取redis裡的數據,如果沒有才會往MySQL裡去讀,當然你的查詢不能是太過複雜的查詢。個人推薦redis,畢竟它可以磁盤落地化。

綜上所述,應該可以解決問題。當然這裡只是提供思路,沒有一種方案是完美的,都需要根據需求去定製。


dba菜鳥


數據量特別大,那只有一個辦法:冷熱分離,冷數據(比較久遠,訪問較少的歷史數據),可以放入mongo,hbase等,當下熱點數據放入mysql


用戶2259999702841


分庫分表是最常規也是最常見的一種解決數據量過大的方式。分表的話也分為垂直分和水平分。下面我列舉一下其他的方式

1、讀寫分離。就是將數據庫的讀寫操作分開,比如讓主服務器讀,從服務器去做寫操作,或者讓性能比較好的服務器去做寫操作,性能不太好的服務器做讀操作;具體如何去讀寫分離,要看我們如何去分了。

2、靜態緩存。分為本地緩存和服務緩存,本地緩存就是將數據加載到本地,服務緩存就是比如使用Redis這樣的k-v數據庫進行存儲熱點數據。但是使用服務緩存也有缺點,最常見的問題就是,“擊穿”,就是假如緩存都失效了,這時候併發請求都去訪問db,此時可能造成服務器掛掉,這個時候為了避免這種情況,一般都是使用互斥量來解決這種問題。

3、系統架構。這個就要看我們整體項目的架構設計,主要是包括SQL操作的設計


JalenZh


不使用分庫分表,可以考慮使用NoSQL,比如MongoDB。

1. 直接切換到MongoDB上。

2. 使用一個數據遷移策略,把舊數據,比如一個月之前的數據遷移到MongoDB裡,MySQL裡只放新生成的數據。


陳述員


數據庫的類型目前有這麼幾種:關係型數據庫,nosql和最近出的newSql和時序數據庫。

能支撐大數據量又保有大部分的關係數據庫的功能,那非newSql數據庫莫屬了。

2012 年 Google 在 OSDI 上發表了 Spanner 的論文,2013 年在 SIGMOD 發表了 F1 的論文。這兩篇論文讓業界第一次看到了關係模型和 NoSQL 的擴展性在超龐大集群規模上融合的可能性。

NewSql數據庫,國外的有CockroachDB,國內的有TiDB,TiDB有pingCap公司出品,國內的大公司已經在使用,有大公司的背書,所以我們公司也在使用,省去了使用mysql手工分庫分表和使用中間件的麻煩。


分享到:


相關文章: