mysql分表+查詢
阿新 • • 發佈:2019-01-31
垂直分表:
其實沒啥好講,就是 主鍵+常用列 放在原表中,再講 主鍵+一些不常用列 放在另外的表中。
這樣一個數據頁就可以存放更多資料。 但是缺點也明顯,可能會增加join 或 union之類的操作。
水平分表:
典型應用:新聞類、qq狀態、朋友圈動態等關注實時或最近的,可以用時間劃分,比如當月一張表,上個月一張表。
2、按區間分
通常每張表都會有個自增id,可以利用自增id分,比如
user1表 是1~50
user2表 是51~100 //insert 操作完成後,判斷id值,超過50w時,建立新表
3、hash分表
實質上沒啥意思,對每一條插入的資料進行取模, 對於單挑記錄查詢還ok,如果查詢相鄰幾行資料時,就悲劇了。 感興趣的同學可以看下面相關連結第一條。
分表後查詢:
1、對於時間水平分表:
假設朋友圈狀態表,每天都會產生20w條記錄, 建表 table_20150401 存放。然後用cron跑一個指令碼,每天晚上凌晨建立新表,比如 table_20150402。在php程中
執行插入的函式進行封裝,使用下面這兩個函式。
新聞或朋友圈狀態id 1~1000 1001~2000
一、資料庫裡面建表 breakup_table //這個表裡專門記錄,新分表和原表的 記錄數,方便確定查詢哪個表
比如: news_1 1 //起始key為1
news_2 1001 //起始key為1001
news_3 2001
二、上述 news_1 之類的資料,第一次需要同資料庫拿,之後可以放到session或memcached裡面
典型user表 //單獨拉出來講,因為比較特別,第一次查詢可能比較花時間,因為必須根據使用者名稱確定去找哪個表
可以這做:
$md5_val = md5($user_name); //用crc32()應該也可以,但未嘗試,如果嘗試記得%u,使其不為負
$first_val = substr($md5_val, 0,1);//然後去取第一個值
$decimal = hexdec($first_val); //十六進位制轉十進位制
$table_num = $decimal%3 + 1; // 求餘3,使得只有三張表,table_1,table_2,table_3
主要原理,利用user_name唯一性,匯出md5唯一性,然後求餘限制分表數量
其實沒啥好講,就是 主鍵+常用列 放在原表中,再講 主鍵+一些不常用列 放在另外的表中。
這樣一個數據頁就可以存放更多資料。 但是缺點也明顯,可能會增加join 或 union之類的操作。
水平分表:
原則:具體情況具體分析。
常見幾種分法:
1、按時間分典型應用:新聞類、qq狀態、朋友圈動態等關注實時或最近的,可以用時間劃分,比如當月一張表,上個月一張表。
2、按區間分
通常每張表都會有個自增id,可以利用自增id分,比如
user1表 是1~50
user2表 是51~100 //insert 操作完成後,判斷id值,超過50w時,建立新表
3、hash分表
實質上沒啥意思,對每一條插入的資料進行取模, 對於單挑記錄查詢還ok,如果查詢相鄰幾行資料時,就悲劇了。 感興趣的同學可以看下面相關連結第一條。
分表後查詢:
1、對於時間水平分表:
假設朋友圈狀態表,每天都會產生20w條記錄, 建表 table_20150401 存放。然後用cron跑一個指令碼,每天晚上凌晨建立新表,比如 table_20150402。在php程中
執行插入的函式進行封裝,使用下面這兩個函式。
2、對於id區間劃分insertData($data){ $table = "table_".date("Ymd",time()); //生成當天表名 insert($data,$table); // 插入新的表中 } GetData($condition){ //如果條件裡面帶了時間查詢,比如:$condition[time] , 則分析出對應表名,選擇對應一張或多張表 $table = "table_".date("Ymd",time()); //生成當天表名 Get($condition,$table); // 在新的表中查詢 }
新聞或朋友圈狀態id 1~1000 1001~2000
一、資料庫裡面建表 breakup_table //這個表裡專門記錄,新分表和原表的 記錄數,方便確定查詢哪個表
比如: news_1 1 //起始key為1
news_2 1001 //起始key為1001
news_3 2001
二、上述 news_1 之類的資料,第一次需要同資料庫拿,之後可以放到session或memcached裡面
3、對於hash分表查詢:insertUser($data){ $table_num = getCurrentNewNum(); //這個值用memcached去包裹,if($count < 2001)return 3;elseif($count < 1001)return 2;else 1; $table = "table_".$table_num); //生成指定表名 insert($data,$table); // 插入新的表中 } GetUser($condition){ $table_num = getCurrentNewNum(); $table = "table_".$table_num); //生成指定表名 Get($condition,$table); // 在新的表中查詢 }
典型user表 //單獨拉出來講,因為比較特別,第一次查詢可能比較花時間,因為必須根據使用者名稱確定去找哪個表
可以這做:
$md5_val = md5($user_name); //用crc32()應該也可以,但未嘗試,如果嘗試記得%u,使其不為負
$first_val = substr($md5_val, 0,1);//然後去取第一個值
$decimal = hexdec($first_val); //十六進位制轉十進位制
$table_num = $decimal%3 + 1; // 求餘3,使得只有三張表,table_1,table_2,table_3
主要原理,利用user_name唯一性,匯出md5唯一性,然後求餘限制分表數量
insertUser($data){
$table = "table_".$table_num); //生成指定表名
insert($data,$table); // 插入新的表中
}
GetUser($condition){
$table = "table_".$table_num); //生成指定表名
Get($condition,$table); // 在新的表中查詢
}
hash 分表也可用於id區間分表,即用id值 取模。
水平分表,典型缺點,對於group by或order by之類的查詢是災難。