資料庫分表和分庫的原理及基於thinkPHP的實現方法,分庫thinkphp
為什麼要分表,分庫:
當我們的資料表資料量,訪問量很大,或者是使用頻繁的時候,一個資料表已經不能承受如此大的資料訪問和儲存,所以,為了減輕資料庫的負擔,加快資料的儲存,就需要將一張表分成多張,及將一類資料存入不同的幾張表,當分表已經不能滿足需求是,我們還可以分庫,及用幾個資料庫儲存。
分表會隨著需求和功能的不同有不同的實現方法,下面是我做項目中的一個例子:
需求:product,product_price兩張表是一對多的關係,及產品和產品每日的價格,一個產品對應幾種價格,現在由於產品表資料量很大,每天多有上百萬條資料,就以天為單位對錶進行分表,以月為單位對資料庫進行分庫,表的命名為‘product_price2014-07-20’表格式:前面是原資料庫表名,後面是日期(年-月-日).
建立資料庫和表的代碼如下:
function get_product_price_table(){ $db_info=array(); //這個月 $newmot_time=date("Y-m"); //今天日期 $newday_time=date("Y-m-d"); //本月資料庫,今天的表 $db_name = 'acbooking'.$newmot_time; $table_name = "product_price".$newday_time; //昨天的日期 $yesday_time = date("Y-m-d",strtotime("-1 day")); //取出昨天的資料,擷取 product_price的最後id,作為新表id的起始值 $last_one_product_price = get_info('product_price_table_id',array('time'=>$yesday_time)); if($last_one_product_price['table_id_end']>0){ $table_id = $last_one_product_price['table_id_end']+1; }else{ $table_id = 1; } //建立資料庫
$Db_string_line = C('DB_TYPE').'://'.C('DB_USER').':'.C('DB_PWD').'@'.C('DB_HOST').'/'.$new_db_database;$DB_P=C('DB_PREFIX');$Model=M($table,$DB_P,$Db_string_line);$db_name=$Model->execute($sql);//通過sql語句配置建立新資料庫新標,此處省略了sql語句
//建立資料表
$Db_string_line = C('DB_TYPE').'://'.C('DB_USER').':'.C('DB_PWD').'@'.C('DB_HOST').'/'.$new_db_database;$DB_P=C('DB_PREFIX');$Model=M($table,$DB_P,$Db_string_line);$table_name=$Model->execute($sql);
//返回新 資料庫,新的表 $db_info['database']=$db_name; $db_info['table']=$table_name; return $db_info;}
建立出分表後,即可儲存當天的所有資料,每天換一張表,執行效率很高。。。。
資料庫為何要分庫分表
1 基本思想之什麼是分庫分表?
從字面上簡單理解,就是把原本儲存於一個庫的資料分Block Storage到多個庫上,把原本儲存於一個表的資料分Block Storage到多個表上。
2 基本思想之為什麼要分庫分表?
資料庫中的資料量不一定是可控的,在未進行分庫分表的情況下,隨著時間和業務的發展,庫中的表會越來越多,表中的資料量也會越來越大,相應地,資料操作,增刪改查的開銷也會越來越大;另外,由於無法進行分布式式部署,而一台伺服器的資源(CPU、磁碟、記憶體、IO等)是有限的,最終資料庫所能承載的資料量、資料處理能力都將遭遇瓶頸。
3 分庫分表的實施策略。
分庫分表有垂直切分和水平切分兩種。
3.1 何謂垂直切分,即將表按照功能模組、關係密切程度劃分出來,部署到不同的庫上。例如,我們會建立定義資料庫workDB、商品資料庫payDB、使用者資料庫userDB、日誌資料庫logDB等,分別用於儲存項目資料定義表、商品定義表、使用者資料表、日誌資料表等。
3.2 何謂水平切分,當一個表中的資料量過大時,我們可以把該表的資料按照某種規則,例如userID散列,進行劃分,然後儲存到多個結構相同的表,和不同的庫上。例如,我們的userDB中的使用者資料表中,每一個表的資料量都很大,就可以把userDB切分為結構相同的多個userDB:part0DB、part1DB等,再將userDB上的使用者資料表userTable,切分為很多userTable:userTable0、userTable1等,然後將這些表按照一定的規則儲存到多個userDB上。
3.3 應該使用哪一種方式來實施資料庫分庫分表,這要看資料庫中資料量的瓶頸所在,並綜合項目的業務類型進行考慮。
如果資料庫是因為表太多而造成海量資料,並且項目的各項商務邏輯劃分清晰、低耦合,那麼規則簡單明了、容易實施的垂直切分必是首選。
而如果資料庫中的表並不多,但單表的資料量很大、或資料熱度很高,這種情況之下就應該選擇水平切分,水平切分比垂直切分要複雜一些,它將原本邏輯上屬於一體的資料進行了物理分割,除了在分割時要對分割的粒度做好評估,考慮資料平均和負載平均,後期也將對項目人員及應用程式產生額外的資料管理負擔。
在現實項目中,往往是這兩種情況兼而有之,這就需要做出權衡,甚至既需要垂直切分,又需要水平切分。我們的遊戲項目便綜合使用了垂直與水平切分,我們首先對資料庫進行垂直切分,然後,再針對一部分表,通常是使用者資料表,進行水平切分。
4 分庫分表存在的問題。
4.1 事務問題。
在執行分庫分表之後,由於資料存放區到了不同的庫上,資料庫交易管理出現了困難。如果依賴資料庫本身的分散式交易管理功能去執行事務,將付出高昂的效能代價;如果由應用程式去協助控制,形成程式邏輯上的事務,又會造成編程方面的負擔。
4.2 跨庫跨表的join問題。
在執行了分庫分表之後,難以避免會將原本邏輯關聯性很強的資料劃分到不同的表、不同的庫上,這時,表的關聯操作將受到限制,我們無法join位於不同分庫的表,也無法join分表粒度不同的表,結果原本一次查詢能夠完成的業務,可能需要多次查詢才能完成。
4.3 額外的資料管理負擔和資料運算壓力。
額外的資料管理負擔,最顯而易見的就是資料的定位問題和資料的增刪改查的重複執行問題,這些都可以通過應用程式解決,但必然引起額外的邏輯運算,例如,對於一個記錄使用者成績的使用者資料表userTable,業務要求查出成績最好的100位,在進行分表之前,只需一個order by語句就可以搞定,但是在進行分表之後,將需要n個order by語句,分別查出每一個分表的前1......餘下全文>>
Thinkphp資料庫分表怎插入新資料?
分表的話一般不自增主鍵,為了保持跟主表的主鍵一致