MySQL 對於千萬級的大表要怎麼優化?

時間 2021-05-07 06:14:40

1樓:架構師

每當看到這種問題,總有一大堆人在下邊回答不搭邊的東西,從網上copy、幾萬字的內容對於問題有意義嗎?

言歸正傳,mysql單錶到達千萬級別確實會有效能瓶頸,不的不說免費的mysql效能和sqlserver,oracel差的太多了。

至於優化,可以做一下幾點:

1。網上都寫爛的分庫分表,但是也要根據具體的業務來具體分,可以參考這個

程式設計師修神之路--做好分庫分表其實很難之一(繼續送書)

2。做表分割槽,但是一定要記住不同的分割槽一定要落在不同的物理磁碟,這樣對整體的io提公升才有效果

3。把大字段拆出來,尤其是那些varchar(2000+)的

3。換sqlserver或者oracle把,mysql對於大資料說實話太費勁

2樓:

前段時間剛好有這個事,為了省錢沒用其他技術方案,表資料一天300W-500W或者更多,不維護前大概4-6億

僅說一些實際經驗體會

早點兒把索引建好,表過5000KW,後期加索引很麻煩。修改字段什麼的也很麻煩。

loaddata比較快,就算是資料清洗你也是處理好,用loaddata的形式入庫,batch insert 之類的不行。用loaddata涉及到結算冪等要重跑,優勢很明顯。

有效能問題問題不要著急研究技術方案,其實查一下slow query,優化一下SQL或者建了索引,可以撐很久,資料也可以清。

不用擔心資料繼續膨脹後撐不住。現在雲伺服器提供商已經封裝了很好的產品出來了,OLAP,OLTP的產品都有,直接找公司申請資源,最終花費遠比你自己搭建自己運維成本低,當然公司其他團隊有搭建好的另說。

後續方案不展開,快取,其餘資料倉儲方案等等。

最後推薦一下阿里雲的產品,OLAP的比如分析型資料庫,會讓你省很多事,過去累積的SQL不用丟,甚至本來寫好的一些結算指令碼,僅需要保留資料清洗部分,查詢可以直接在這個資料庫上裸算,專案到了這個級別還有頻繁的多維查詢問題,就已經是初級資料倉儲問題了,和老闆講清楚這個成本是應該掏的。

3樓:五星程式設計師

MySQL效能優化詳解 https://www.

cppentry.com/bencandy.php?src=weibo&fid=57&aid=1205VC程式設計輕鬆獲取區域網連線通知 https://www.

cppentry.com/bencandy.php?src=weibo&fid=55&aid=2138常見的C語言記憶體錯誤及對策 https://www.

cppentry.com/bencandy.php?src=weibo&fid=45&aid=2299計算機二級C語言上機真題(2)【附詳解】 https://www.

cppentry.com/bencandy.php?src=weibo&fid=41&aid=2551計算機二級C語言上機真題(7)【附詳解】 https://www.

cppentry.com/bencandy.php?src=weibo&fid=41&aid=2556C語言變長陣列 https://www.

cppentry.com/bencandy.php?src=weibo&fid=45&aid=3114VC模仿超炫QQ介面的實現 https://www.

cppentry.com/bencandy.php?src=weibo&fid=55&aid=3154VC++內部COM外掛程式的程式設計實現 https://www.

cppentry.com/bencandy.php?src=weibo&fid=55&aid=3156顏色對話方塊使用例項 https://www.

cppentry.com/bencandy.php?src=weibo&fid=55&aid=3178七種排序演算法的簡單分析 https://www.

cppentry.com/bencandy.php?src=weibo&fid=0&aid=3331c++中常見問題 https://www.

cppentry.com/bencandy.php?src=weibo&fid=45&aid=3545C++一維陣列和指標的關係總結 https://www.

cppentry.com/bencandy.php?src=weibo&fid=49&aid=3635C++ 擴充套件和嵌入 Python(1) https://www.

src=weibo&fid=49&aid=37304.3.3 Dialog結構(基於對話方塊的窗體) https:

//www.

cppentry.com/bencandy.php?src=weibo&fid=49&aid=38715.4.1 鄰域平均法 https://www.

cppentry.com/bencandy.php?src=weibo&fid=49&aid=42265.4.4 中值濾波(1) https://www.

cppentry.com/bencandy.php?src=weibo&fid=49&aid=425015.16 如何獲得系統資料夾路徑 https://www.

cppentry.com/bencandy.php?src=weibo&fid=49&aid=43518.2.2 設定唯讀編輯框 https://www.

4樓:小王子

5樓:當代庖丁

針對從頭到尾只使用MySQL的情況來考慮

說一下這種場景下考慮解決方法的順序:

1)優化SQL和索引:有效利用慢查詢、Profiling、Explain來做優化

2)增加快取:利用Redis或者Mem來快取查詢結果。

3)讀寫分離。

4)合理利用分割槽表:分割槽表是MySQl自身實現的優化查詢的方法,對業務層是無感知的,所以可以優先考慮。

5)服務拆分:也是可以認為分庫,針對每個服務設定單獨的資料庫,提高響應速度。

6)針對業務流程進行分表。

6樓:沈杰

這個問題,我看很多回答都已經從很多方面概況性的論述了,整體看,說來說去其實基本也就這麼些東西。但是如果想做好這裡面的每一步則是不容易的,大家只是談了個方案概念。我先簡單談一下自己的整體認識:

拋開具體的業務不談,在純技術的角度通常的解決方案:

第一:成本最低也是最實用的方式:索引優化、sql優化。

第二:上快取,查詢也不一定完全就是資料量大影響的,高訪問量請求資料庫密集時,影響也很大,用快取擋在mysql前面,進行流量削鋒。

第三:分庫,把乙個資料庫,根據業務的耦合度、功能的劃分,拆成若干個小的庫,每個庫只保留共同需要的資料就行了,比如使用者表,這通常在每個庫中都會有相同的乙份。

第五:mysql讀寫分離,這是在乙個庫中又從讀和寫的層面上進行分流,一庫,兩台伺服器,一台只負責讀,另一台只負責寫。其實本質也是一種負載均衡的實現方式

第六:分布式,把同乙份資料分到不同伺服器上,這個成本就大了,一般的公司用不到,較難解決的問題是在資料的一致性上。可以使用一些現成的中介軟體。

等等,不管使用什麼技術,一定要考慮好這個技術可能帶來的後果尤其弊端是什麼。

回到最上面說的 ,要想做好這裡面每一步則又是乙個比較大的問題,比如索引、sql語句的優化,什麼時候能用上索引,什麼時候用不上,多列索引又是什麼情況,乙個多列索引很多時候並不是能完全用上所有列的索引,有時候只會用上第一列,那什麼情況下能用上,什麼情況下用不上,都需要對這些有詳細的了解。

關於這一塊,我在知乎上也答過一些問題,因為有教學從業經驗,所以內容又能很容易看懂,獲得了一些人的好評和認可。

mysql索引最左匹配原則的理解?

MySQL 查詢 select * from table where id in (幾百或幾千個 id) 如何提高效率?

現在網際網路應用的資料量越來越大,企業對資料庫優化看的越來越重,同樣也是面試必問項,答好了更是加分項。

所以最後,我就又寫了一些東西,整理成了筆記,有需要的,可以按以下方式免費獲取。

7樓:猿馬

想要很好地優化mysql,就必須對mysql的各種原理爛熟於心才行,否則只能是狗咬刺蝟,無從下手,至於怎麼才能全面深入了解mysql,之前看過一篇文章

jianshu.com/p/288f8809b151)寫的挺好的,建議看一下

8樓:Kim Young

對於這個,MySQL沒什麼更好的辦法,唯一的就是分表分庫,然後做乙個類似mycat的路由分表合併的埠,要麼資料分層,歷史資料弄到MongDB等別的庫上,總之減少後端互動需要的資料量。

9樓:holmes zang

好多人在說千萬資料不算什麼,你們不能這麼就事論事啊,題主的意思無非就是資料量大了怎麼優化,你們要是覺得千萬資料小case,那改成千億不就行了,再不行再加幾個0。何必在這上面糾結。

我個人的理解,既然表大了,那麼就把它幹小。

10樓:恆小發

實用預警:回答將以實際專案經驗為例,為你解讀優化的奧義!

首先採用Mysql儲存千億級的資料,確實是一項非常大的挑戰。Mysql單錶確實可以儲存10億級的資料,只是這個時候效能非常差,專案中大量的實驗證明,Mysql單錶容量在500萬左右,效能處於最佳狀態。

針對大表的優化,主要是通過資料庫分庫分表來解決,目前比較普遍的方案有三個:分割槽,分庫分表,NoSql/NewSql。實際專案中,這三種方案是結合的,目前絕大部分系統的核心資料都是以RDBMS儲存為主,NoSql/NewSql儲存為輔。

首先來了解一下分割槽方案。分割槽表是由多個相關的底層表實現的。這些底層表也是由控制代碼物件表示,所以我們也可以直接訪問各個分割槽,儲存引擎管理分割槽的各個底層表和管理普通表一樣(所有的底層表都必須使用相同的儲存引擎),分割槽表的索引只是在各個底層表上各自加上乙個相同的索引。

這個方案對使用者遮蔽了sharding的細節,即使查詢條件沒有sharding column,它也能正常工作(只是這時候效能一般)。不過它的缺點很明顯:很多的資源都受到單機的限制,例如連線數,網路吞吐等。

如何進行分割槽,在實際應用中是乙個非常關鍵的要素之一。

下面開始舉例:以客戶資訊為例,客戶資料量5000萬加,專案背景要求儲存客戶的銀行卡繫結關係,客戶的證件繫結關係,以及客戶繫結的業務資訊。此業務背景下,該如何設計資料庫呢。

專案一期的時候,我們建立了一張客戶業務繫結關係表,裡面冗餘了每一位客戶繫結的業務資訊。基本結構大致如下:

查詢時,對銀行卡做索引,業務編號做索引,證件號做索引。隨著需求大增多,這張表的索引會達到10個以上。而且客戶解約再簽約,裡面會儲存兩條資料,只是繫結的狀態不同。

假設我們有5千萬的客戶,5個業務型別,每位客戶平均2張卡,那麼這張表的資料量將會達到驚人的5億,事實上我們系統使用者量還沒有過百萬時就已經不行了。這樣的設計絕對是不行的,無論是插入,還是查詢,都會讓系統崩潰。

mysql資料庫中的資料是以檔案的形勢存在磁碟上的,預設放在/mysql/data下面(可以通過my.cnf中的datadir來檢視), 一張表主要對應著三個檔案,乙個是frm存放表結構的,乙個是myd存放表資料的,乙個是myi存表索引的。這三個檔案都非常的龐大,尤其是.

myd檔案,快5個G了。下面進行第一次分割槽優化,Mysql支援的分割槽方式有四種:

在我們的專案中,range分割槽和list分割槽沒有使用場景,如果基於繫結編號做range或者list分割槽,繫結編號沒有實際的業務含義,無法通過它進行查詢,因此,我們就剩下 HASH 分割槽和 KEY 分割槽了,HASH分割槽僅支援int型別列的分割槽,且是其中的一列。 KEY 分割槽倒是可以支援多列,但也要求其中的一列必須是int型別;看我們的庫表結構,發現沒有哪一列是int型別的,如何做分割槽呢?增加一列,繫結時間列,將此列設定為int型別,然後按照繫結時間進行分割槽,將每一天繫結的使用者分到同乙個區裡面去。

這次優化之後,我們的插入快了許多,但是查詢依然很慢,為什麼?

因為在做查詢的時候,我們也只是根據銀行卡或者證件號進行查詢,並沒有根據時間查詢,相當於每次查詢,mysql都會將所有的分割槽表查詢一遍。進行第二次方案優化,既然 HASH 分割槽和 KEY分割槽要求其中的一列必須是int型別的,那麼創造出乙個int型別的列出來分割槽是否可以?分析發現,銀行卡的那串數字有秘密。

銀行卡一般是16位到19位不等的數字串,我們取其中的某一位拿出來作為表分割槽是否可行呢,通過分析發現,在這串數字中,其中確實有一位是0到9隨機生成的,我們基於銀行卡號+隨機位進行KEY分割槽,每次查詢的時候,通過計算截取出這位隨機位數字,再加上卡號,聯合查詢,達到了分割槽查詢的目的,需要說明的是,分割槽後,建立的索引,也必須是分割槽列,否則Mysql還是會在所有的分割槽表中查詢資料。

通過銀行卡號查詢繫結關係的問題解決了,那麼證件號呢,如何通過證件號來查詢繫結關係。前面已經講過,做索引一定是要在分割槽健上進行,否則會引起全表掃瞄。我們再建立了一張新錶,儲存客戶的證件號繫結關係,每位客戶的證件號都是唯一的,新的證件號繫結關係表裡,證件號作為了主鍵,那麼如何來計算這個分割槽健呢,客戶的證件資訊比較龐雜,有身份證號,港澳台通行證,機動車駕駛證等等,如何在無序的證件號裡找到分割槽健。

為了解決這個問題,我們將證件號繫結關係表一分為二,其中的一張表專用於儲存身份證型別的證件號,另一張表則儲存其他證件型別的證件號,在身份證型別的證件繫結關係表中,我們將身份證號中的月數拆分出來作為了分割槽健,將同乙個月出生的客戶證件號儲存在同乙個區,這樣分成了12個區,其他證件型別的證件號,資料量不超過10萬,就沒有必要進行分割槽了。這樣每次查詢時,首先通過證件型別確定要去查詢哪張表,再計算分割槽健進行查詢。作了分割槽設計之後,儲存2000萬使用者資料時銀行卡表的資料儲存檔案就分成了10個小檔案,證件表的資料儲存檔案分成了12個小檔案,解決了這兩個查詢的問題,還剩下乙個問題:

業務編號怎麼辦?乙個客戶有多個簽約業務,如何進行儲存?這時候,採用分割槽的方案就不太合適了,它需要用到分表的方案。

我們前面有提到過對於mysql,其資料檔案是以檔案形式儲存在磁碟上的。當乙個資料檔案過大時,作業系統對大檔案的操作就會比較麻煩耗時,且有的作業系統就不支援大檔案,這個時候就必須分表了。另外對於mysql常用的儲存引擎是Innodb,它的底層資料結構是B+樹。

當其資料檔案過大的時候,查詢乙個節點可能會查詢很多層次,而這必定會導致多次IO操作進行裝載進記憶體,肯定會耗時的。除此之外還有Innodb對於B+樹的鎖機制。對每個節點進行加鎖,那麼當更改表結構的時候,這時候就會樹進行加鎖,當表檔案大的時候,這可以認為是不可實現的。

所以綜上我們就必須進行分表與分庫的操作。

如何進行分庫分表,目前網際網路上有許多的版本,比較知名的一些方案:阿里的TDDL,DRDS和cobar,京東金融的sharding-jdbc;民間組織的MyCAT;360的Atlas;美團的zebra;其他比如網易,58,京東等公司都有自研的中介軟體。

這麼多的分庫分表中介軟體方案歸總起來,就兩類:client模式和proxy模式。

client模式

proxy模式

無論是client模式,還是proxy模式。幾個核心的步驟是一樣的:SQL解析,重寫,路由,執行,結果歸併。

個人比較傾向於採用client模式,它架構簡單,效能損耗也比較小,運維成本低。

如何對業務型別進行分庫分表。分庫分表最重要的一步,即sharding column的選取,sharding column選擇的好壞將直接決定整個分庫分表方案最終是否成功。而sharding column的選取跟業務強相關。

在我們的專案場景中,sharding column無疑最好的選擇是業務編號。通過業務編號,將客戶不同的繫結簽約業務儲存到不同的表裡面去,根據業務編號路由到相應的表中進行查詢,達到進一步優化sql的目的。

mysql某千萬級資料表中某字段有100多種取值,該欄位適合加索引嗎?

100 10000000 隨便乙個取值對應都平均有10W條對應的,效率不高,占用的空間太高.但是如果這個條件是每次查詢必須的話,還是需要加上,效率的話聊勝於無.如果這個條件是偶爾查詢會用到的話,那麼價效比就太低,不建議加.所以結論就是看你這個查詢條件用的多不多,有沒有佔80 的查詢以上.還有就是,分...

大量讀寫的mysql表怎麼優化?

混血王子 和我的業務類似,但是我沒你這麼大的量。我覺得redis的部分保留,水平分表應該不錯的,另外統計部分用中間表統計。還有就是提供你乙個思路,order用mongodb來存可能好點 已登出 從你的問題描述上看可以使用分庫設計。首先單庫在1千萬時出現效能障礙。我們假設1千萬是單機單庫的效能極限。可...

MySQL中2個表的查詢結果疑問

關鍵 我理解的SQL有乙個很重要的一點,是找出不同表的關係,及它們之間的連線路徑。你提供的兩張表你自己應該明確知道,student表中的ID對應的是score表中的ID,如果你能明確這點在SQL語言的中的意義就好寫了。關於你的題,自己想下簡單關係,然後寫成SQL 兩個表靠ID進行關聯,關係是stud...