一、場景說明
1、為什么要進行分表
隨著數據量的不斷增大,一張表中的數據肯定也會越來越多,甚至達到百萬甚至千萬級。我們通常會通過搭建mysql集群(主從同步),讀寫分離來實現優化數據庫查詢執行效率。
但是由于數據表本身是具有表鎖(myisam)以及行鎖(innodb)的。表鎖定表示你們都不能對這張表進行操作,必須等我對表操作完才行。行鎖定也一樣,別的sql必須等我對這條數據操作完了,才能對這條數據進行操作。這樣就導致如果我們對一張表進行增刪改操作時,mysql就會進行表鎖或者行鎖,導致其他的sql排隊時間增長。
為了減輕表鎖和行鎖帶來的其他sql執行時間延長的問題,我們就需要對數據表進行分表。如果對數據表進行分表操作,把一張表分成10張表,那肯定會減少其他sql的排隊時間,進而提高sql的執行效率。
注:主從同步:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/81086243
?
二、開始分表
一張數據表中有uid 0000001? ?到? ?uid = 50000000 條數據。
代碼示例:
<?phpfunction getUserInfoTable($uid)
{$i = $uid % 10;$table = sprintf("user_info_%s", $i);$check_sql = "SELECT COUNT(1) exist from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND table_name ='{$table}' ";$result = $this->link->fetchOne($check_sql);$sql = <<<EOD
CREATE TABLE IF NOT EXISTS `{$table}` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用戶ID',`comic_id` int(10) unsigned NOT NULL DEFAULT '0',`chapter_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '章節ID',`t` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '時間',`read_status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '閱讀狀態 1已閱讀 2未閱讀',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
EOD;if ($result['exist'] == 0) {$this->link->execute($sql);}return $table;
}
?注:如果已經有一些數據了,這時理論上也是可以采用上面這種方式進行分表的。
比如已經有20萬條數據,這時我才開始意識到這張表需要進行分表了,這時候怎么辦呢?我們可以這樣,for循環uid,并對uid進行取模,或者是直接用uid的范圍進行劃分,根據一定算法(比如上面就是對uid進行取模)查出此uid應該在哪張分表后的數據表中,比如uid = 1000085,取模之后就要在user_info_5 這張數據表中。那我們就將查詢出的uid = 1000085的用戶信息插入到新數據表user_info_5中,循環插入之后,未分表之前的數據就都復制到了對應的數據表中。
當然,這只是其中的一種方式,還有其他方式。有自己想法的朋友可以在下方留言互相討論。
?
?
?