「分庫分表」思想理解筆記

2021-09-21 13:14:27 字數 2681 閱讀 1337

當一張表中的資料達到幾千萬條時,對錶進行一次查詢所花的時間將會變長。這時候,如果有聯合查詢的話,可能會卡死在那兒,甚至把系統給拖垮。

而分庫分表的目的就在於此:減小資料庫的負擔,提高資料庫的效率,縮短查詢時間。另外,因為分庫分表這種改造是可控的,底層還是基於rdbms(關聯式資料庫管理系統),因此整個資料庫的運維體系以及相關基礎設施都是可重用的。

假設目前我們的系統有將近20億條資料,每張表中的資料最大的接近600w條,每條資料大約3k,每個表將近1.5g的資料。我們將會遇到的問題:查詢經常超時,單條sql執行count(*)查詢時間達到了最大260ms,0.26s(標準是超過0.1s的資料為慢sql)。

為了說明我們為什麼要分庫分表,我們看一下sql的執行過程。

mysql執行一條sql的過程如下:

收到sql語句

把sql放到排隊佇列中

執行sql

返回結果

在這個執行過程中最花時間的地方在於:

排隊等待的時間

sql的執行時間

如果有2個sql語句都要同時修改同一張表的同一條資料,mysql對這種情況的處理是:一種是表鎖定(myisam儲存引擎),乙個是行鎖定(innodb儲存引擎)

表鎖定表示其他操作都不能對這張表進行操作,必須等當前對錶的操作完才行。行鎖定也一樣,別的sql必須等這條資料操作完了,其他人才能對這條資料進行操作。

如果資料太多,一次執行的時間太長,等待的時間就越長,這也是我們為什麼要分表的原因。

不同的資料庫,同步相同的資料,分別只負責資料的讀和寫;

指定分割槽列表示式,把記錄拆分到不同的區域中(必須是同一伺服器,可以是不同硬碟),應用看來還是同一張表,沒有變化;

乙個系統的多張資料表,儲存到多個資料庫例項中;

對於一張多行(記錄)多列(字段)的二維資料表,又分兩種情形:

在實際生產中,通常的進化過程是:

單庫單錶->單庫多表->多庫多表

分割槽->分表->分庫垂直分庫 - 水平分庫 - 讀寫分離

單庫單錶是最常見的資料庫設計,例如,有一張訂單表(order)放在資料庫中,所有的訂單都可以在order表中查到。

隨著訂單數量的增加,order表的資料量會越來越大,當資料量達到一定程度的時候,對order表的查詢會變慢,從而影響整個db的效能

另外,隨著需求的迭代,如果增加新增一列的時候,mysql會鎖表,期間所有的讀寫操作只能等待,別無他法。

這時候,可以將order進行水平的切分,產生多個表結構完全一樣的order表。比如:order_01,order_02....,order_n,那麼order_01+order_02+order_n的資料是乙份完整的訂單資料。

這個水平切分,簡單的做法如:

按數量切分,1~1000的存在第一張表,1001~2000存在第二張表;

按時間切分,比如:2023年1月份存在第一張表,2023年2月份存在第二張表;還可以按照id的雜湊值進行切分,等等等等

隨著資料量增加,單台資料庫的硬體儲存不夠了,並且,隨著查詢量的增加,單台資料庫伺服器已經沒辦法支撐。這時候就需要對資料庫進行水平區分。

比如按地區分庫,乙個省份在乙個物理資料庫等等

任何事情都有兩面性,分庫分表也不例外,如果採用分庫分表,會引入新的的問題

1.分布式事務問題

做了垂直分庫或者水平分庫以後,就必然會涉及到跨庫執行sql的問題,就會引發網際網路界的老大難問題-"分布式事務"。那麼要如何解決這個問題呢?

2.跨庫join的問題

分庫分表後,表之間的關聯操作將受到限制,就無法join位於不同分庫的表,也無法join分表粒度不同的表, 結果原本一次查詢能夠完成的業務,可能需要多次查詢才能完成。

那麼要如何解決這個問題呢?

簡單的解決方法:

3.橫向擴容的問題

當我們使用雜湊取模做分表的時候,針對資料量的遞增,可能需要動態的增加表,此時就需要考慮資料遷移的問題。

原來使用的是hash後對8進行取模,那麼,資料是均分在8個表(庫)上。

如果8個表不夠的時候,我們要擴充套件到16個表,這時候,我們hash後對16取模,新資料是沒有問題的,舊資料就會發生錯亂

如果雜湊後是9,那麼,原來我們對8取模後,是1,會到表1進行查詢;但是,現在我們是對16取模,那麼是到表9進行查詢的,而這個資料在表9又不存在,因此,就會找不到資料了

4.結果集合並、排序的問題

因為我們是將資料分散儲存到不同的庫、表裡的,當我們查詢指定資料列表時,資料**於不同的子庫或者子表,就必然會引發結果集合並、排序的問題。

如果每次查詢都需要排序、合併等操作,效能肯定會受非常大的影響。

上面列出了分庫分表的常見的一些,總的來說:

1、能不切分盡量不要切分,如果沒有達到幾百萬,通常無需分庫分表

2、如果一定要切分,一定要選擇合適的切分規則,提前規劃好。

3、如果一定要切分,盡量通過資料冗餘或表分組來降低跨庫 join 的可能。對於現在市面上有好幾種資料庫中介軟體,這些中介軟體對資料 join 實現,箇中滋味,只能自己體會。業務讀取盡量少使用多表 join。

4、資料盡可能的比較均勻分布資料到各個節點上

對於分庫分表的入門理解

資料庫出現效能瓶頸。用大白話來說就是資料庫快扛不住了。資料庫出現效能瓶頸,對外表現有幾個方面 從機器的角度看,效能瓶頸無非就是cpu 記憶體 磁碟 網路這些。要解決效能瓶頸最簡單粗暴的辦法就是提公升機器效能,但是通過這種方法成本和收益投入比往往又太高了,不划算,所以重點還是要從軟體角度入手。硬體層面...

mysql分表分庫實現 MySql分表分庫思路

一.資料庫瓶頸 1.1io瓶頸 第一種 磁碟讀io瓶頸,熱點資料太多,資料庫快取放不下,每次查詢時會產生大量的io 分庫和垂直分表 第二種 網路io瓶頸,請求的資料太多,網路頻寬不夠 分庫 1.2cpu瓶頸 第一種 sql問題,如sql中包含join,group by,order by,非索引字段條...

MySQL範圍分表分庫 mysql 分表分庫策略

唯一id的生成 下面列舉幾種常見的唯一id生成方案,需要滿足兩大核心需求 1.全域性唯一 2趨勢有序 1.用資料庫的auto increment 自增id 來生成,每次通過寫入資料庫一條記錄,利用資料庫id自增的特性獲取唯一,有序的id。優點 使用資料庫原有的功能,相對簡單 能夠保證唯一 能夠保證遞...