本文**:
當一張表的資料達到幾千萬時,查詢一次所花的時間會變長。這時候,如果有聯合查詢的話,可能會卡死在那兒,甚至把系統給拖垮。
而分庫分表的目的就在於此:減小資料庫的負擔,提高資料庫的效率,縮短查詢時間。另外,因為分庫分表這種改造是可控的,底層還是基於rdbms,因此整個資料庫的運維體系以及相關基礎設施都是可重用的。
目前我們系統將近20億資料,每張表最大的接近600w條/表,每條資料大約3k,每個表將近1.5g的資料。查詢經常超時,單條sql執行count(*)查詢時間達到了最大260ms,0.26s(標準是超過0.1s的資料為慢sql)。
為了說明我們為什麼要分庫分表,我們看一下sql的執行過程。
mysql執行一條sql的過程如下:
1、收到sql
2、把sql放到排隊佇列中
3、執行sql
4、返回結果
在這個執行過程中最花時間的地方在於:
1.排隊等待的時間,
2.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的問題,就會引發網際網路界的老大難問題-"分布式事務"。那麼要如何解決這個問題呢?
使用分布式事務中介軟體使用mysql自帶的針對跨庫的事務一致性方案(xa),不過效能要比單庫的慢10倍左右。能否避免掉跨庫操作(比如將使用者和商品放在同乙個庫中)2.跨庫join的問題
分庫分表後,表之間的關聯操作將受到限制,就無法join位於不同分庫的表,也無法join分表粒度不同的表, 結果原本一次查詢能夠完成的業務,可能需要多次查詢才能完成。
那麼要如何解決這個問題呢?
簡單的解決方法:
全域性表:基礎資料,所有庫都拷貝乙份。字段冗餘:把需要join的字段冗餘在各個表中,這樣有些欄位就不用join去查詢了。系統層組裝:應用端先分別查詢出所有複核條件的,然後在應用端組裝起來,類似於乙個mapreduce的過程(較複雜)。3.橫向擴容的問題
當我們使用雜湊取模做分表的時候,針對資料量的遞增,可能需要動態的增加表,此時就需要考慮資料遷移的問題。
原來使用的是hash後對8進行取模,那麼,資料是均分在8個表(庫)上。
如果8個表不夠的時候,我們要擴充套件到16個表,這時候,我們hash後對16取模,新資料是沒有問題的,舊資料就會發生錯亂。
如果雜湊後是9,那麼,原來我們對8取模後,是1,會到表1進行查詢;但是,現在我們是對16取模,那麼是到表9進行查詢的,而這個資料在表9又不存在,因此,就會找不到資料了
4.結果集合並、排序的問題
因為我們是將資料分散儲存到不同的庫、表裡的,當我們查詢指定資料列表時,資料**於不同的子庫或者子表,就必然會引發結果集合並、排序的問題。
如果每次查詢都需要排序、合併等操作,效能肯定會受非常大的影響。
上面列出了分庫分表的常見的一些,總的來說:
能不切分盡量不要切分,如果沒有達到幾百萬,通常無需分庫分表如果一定要切分,一定要選擇合適的切分規則,提前規劃好。如果一定要切分,盡量通過資料冗餘或表分組來降低跨庫 join 的可能。對於現在市面上有好幾種資料庫中介軟體,這些中介軟體對資料 join 實現,箇中滋味,只能自己體會。業務讀取盡量少使用多表 join。資料盡可能的比較均勻分布資料到各個節點上
為什麼要分庫分表
初學者在看到這個問題的時候,可能首先想到的是 mysql 一張表到底能存放多少條資料?根據 mysql 官方文件的介紹,mysql 理論上限是232 受限於32位軟體 條資料,然而實際操作中,往往還受限於下面兩條因素 myisamdatapointersize,mysql 的 myisamdatap...
mysql為什麼要分庫分表?
1 基本思想之什麼是分庫分表?從字面上簡單理解,就是把原本儲存於乙個庫的資料分塊儲存到多個庫上,把原本儲存於乙個表的資料分塊儲存到多個表上。2 基本思想之為什麼要分庫分表?單錶運算元據量有最優值,mysql為1000萬左右 可以減輕資料庫的壓力,不用所有執行緒都查同乙個資料庫 資料庫中的資料量不一定...
資料庫為什麼要分庫分表
1 基本思想之什麼是分庫分表?從字面上簡單理解,就是把原本儲存於乙個庫的資料分塊儲存到多個庫上,把原本儲存於乙個表的資料分塊儲存到多個表上。2 基本思想之為什麼要分庫分表?資料庫中的資料量不一定是可控的,在未進行分庫分表的情況下,隨著時間和業務的發展,庫中的表會越來越多,表中的資料量也會越來越大,相...