相对于水平拆分来说,垂直拆分比较容易实现一些,垂直拆分的意思是把数据库中不同的业务数据拆分到不同的数据库中。垂直拆分能很好的起到分散数据库压力的作用。业务模块不明晰,耦合(表关联)度比较高的系统不适合使用这种拆分方式。
有得用户查询积分快,有的用户查询自己的订单很快,但是查询自己的用户信息很慢,为什么?
2,垂直切分的优点
◆ 数据库的拆分简单明了,拆分规则明确;
◆ 应用程序模块清晰明确,整合容易;
◆ 数据维护方便易行,容易定位;
3,垂直切分的缺点
◆ 部分表关联无法在数据库级别完成,需要在程序中完成;
◆ 对于访问极其频繁且数据量超大的表仍然存在性能平静,不一定能满足要求;
◆ 事务处理相对更为复杂;
◆ 切分达到一定程度之后,扩展性会遇到限制;
◆ 过读切分可能会带来系统过渡复杂而难以维护。
针对于垂直切分可能遇到数据切分及事务问题,在数据库层面实在是很难找到一个较好的处理方案。实际应用案例中,数据库的垂直切分大多是与应用系统的模块相对应,同一个模块的数据源存放于同一个数据库中,可以解决模块内部的数据关联问题。而模块与模块之间,则通过应用程序以服务接口方式来相互提供所需要的数据。虽然这样做在数据库的总体操作次数方面确实会有所增加,但是在系统整体扩展性以及架构模块化方面,都是有益的。
可能在某些操作的单次响应时间会稍有增加,但是系统的整体性能很可能反而会有一定的提升。而扩展瓶颈问题。
4,拆分规则
根据模块拆分,比如用户模块、订单模块、日志模块,系统参数模块
用户模块的表:uc_user表;uc_user_info表;uc_action表;uc_profile表
订单模块表:order_action表;order_list表;shop表;order表;
日志模块:order_log表;uc_log表;plocc_log表;
系统参数模块:plocc_parameter表;
模块模块之间都一看都是有联系的,这些都是用到用户的,那么都和用户模块有关联
如下图所示:
5,垂直拆分演示
5.1准备
MySQL环境
创建多实例参考:
建库sql语句:
--1 用户模块 3307端口数据库
create database user_db;
CREATE TABLE user_db.`uc_user` (
`user_id` bigint(20) NOT NULL,
`uc_name` varchar(200) DEFAULT NULL,
`created_time` datetime DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
grant insert,update,delete,select on user_db.* to tim@'192.168.%' identified by 'timgood2013';
-- 查询
mysql
--socket=/usr/local/mysql3307/mysql.sock -e "select * from user_db.uc_user;";
--2 订单模块 3308端口数据库
create database order_db;
CREATE TABLE order_db.`order` (
`order_id` bigint(20) NOT NULL,
`shop_id` varchar(200) DEFAULT NULL,
`created_time` datetime DEFAULT NULL,
`user_id` bigint(20) not null,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
grant insert,update,delete,select on order_db.* to tim@'192.168.%' identified by 'timgood2013';
-- 查询
mysql
--socket=/usr/local/mysql3308/mysql.sock -e "select * from order_db.order;";
--3 日志模块 3309端口数据库
create database log_db;
CREATE TABLE log_db.`order_log` (
`orlog_id` bigint(20) NOT NULL,
`order_id` varchar(200) DEFAULT NULL,
`created_time` datetime DEFAULT NULL,
`user_id` bigint(20) not null,
`action` varchar(2000) not null,
PRIMARY KEY (`orlog_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
grant insert,update,delete,select on log_db.* to tim@'192.168.%' identified by 'timgood2013';
-- 查询
mysql
--socket=/usr/local/mysql3309/mysql.sock -e "select * from log_db.order_log;";
--4 参数模块 33310端口数据库
create database plocc_db;
CREATE TABLE plocc_db.`plocc_parameter` (
`plocc_id` bigint(20) NOT NULL,
`pname` varchar(200) DEFAULT NULL,
`created_time` datetime DEFAULT NULL,
`status` bigint(20) not null,
`creator` bigint not null,
PRIMARY KEY (`plocc_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
grant insert,update,delete,select on plocc_db.* to tim@'192.168.%' identified by 'timgood2013';
--
5.2 演示
Java代码
package mysql;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class MySQLTest2 {
public static long user_id;
public static void main(String[] args) {
MySQLTest2 mt=
new MySQLTest2();
/* 录入用户数据
BigInteger user_id0 = new BigInteger("10001");
Connection conn=mt.getConn("user_db");
mt.insertUser(conn, bi, "tim--"+user_id0.longValue());
*/
/* 录入日志数据
Connection conn2=mt.getConn("log_db");
BigInteger user_id = new BigInteger("10001");
BigInteger order_id = new BigInteger("20150531001");
BigInteger orlog_id = new BigInteger("20150531001");
mt.insertLog(conn2, user_id,order_id , orlog_id, "create a order for tim");
*/
//录入订单数据
Connection conn3=mt.getConn(
"order_db");
BigInteger user_id2 =
new BigInteger(
"10001");
BigInteger order_id2 =
new BigInteger(
"20150531001");
BigInteger shop_id2 =
new BigInteger(
"20150531001");
mt.insertOrder(conn3,order_id2 , shop_id2, user_id2);
}
// 获取数据库的连接,如果扩展的话,可以单独做一个接口提供给程序员来调用它
// String type:连接的数据类型
public Connection
getConn(String type ) {
String port=
"3307";
if (type==
"user_db" ){
port=
"3307";
}
else if(type==
"order_db"){
port=
"3308";
}
else if(type==
"log_db"){
port=
"3309";
}
else if(type==
"plocc_db") {
port=
"3310";
}
else{
port=
"3311";
}
Connection conn =
null;
try {
Class.forName(
"com.mysql.jdbc.Driver");
}
catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String url =
"jdbc:mysql://192.168.52.130:"+port+
"/"+type;
try {
conn = DriverManager.getConnection(url,
"tim",
"timgood2013");
}
catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(
"the current db is :"+url);
return conn;
}
// 获取日期字符串
public String
getTimeByCalendar(){
/*
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);//获取年份
int month=cal.get(Calendar.MONTH);//获取月份
int day=cal.get(Calendar.DATE);//获取日
int hour=cal.get(Calendar.HOUR);//小时
int minute=cal.get(Calendar.MINUTE);//分
int second=cal.get(Calendar.SECOND);//秒
String strdate=year+"-"+month+"-"+day+" "+hour+":"+minute+":"+second;
*/
SimpleDateFormat df =
new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
//设置日期格式
System.out.println(df.format(
new Date()));
// new Date()为获取当前系统时间
return df.format(
new Date());
}
// 开始录入用户数据
public int insertUser(Connection cnn,BigInteger user_id,String name){
String sql=
"insert into user_db.uc_user(user_id,uc_name,created_time)values(?,?,?)";
int i=
0;
long uid = user_id.longValue();
Connection conn=cnn;
try{
PreparedStatement preStmt =conn.prepareStatement(sql);
preStmt.setLong(
1, uid);
preStmt.setString(
2,name);
preStmt.setString(
3,getTimeByCalendar());
i=preStmt.executeUpdate();
}
catch (SQLException e)
{
e.printStackTrace();
}
return i;
//返回影响的行数,1为执行成功
}
// 开始录入日志数据
public int insertLog(Connection cnn,BigInteger user_id,BigInteger order_id,BigInteger orlog_id,String action){
String sql=
"insert into log_db.order_log(orlog_id,order_id,created_time,user_id,action)values(?,?,?,?,?)";
int i=
0;
Connection conn=cnn;
try{
PreparedStatement preStmt =conn.prepareStatement(sql);
preStmt.setLong(
1, user_id.longValue());
preStmt.setLong(
2, order_id.longValue());
preStmt.setString(
3,getTimeByCalendar());
preStmt.setLong(
4, orlog_id.longValue());
preStmt.setString(
5,action);
i=preStmt.executeUpdate();
}
catch (SQLException e)
{
e.printStackTrace();
}
return i;
//返回影响的行数,1为执行成功
}
// 开始录入订单数据
public int insertOrder(Connection cnn,BigInteger order_id,BigInteger shop_id,BigInteger user_id){
String sql=
"insert into order_db.order(order_id,shop_id,created_time,user_id)values(?,?,?,?)";
int i=
0;
Connection conn=cnn;
try{
PreparedStatement preStmt =conn.prepareStatement(sql);
preStmt.setLong(
1, order_id.longValue());
preStmt.setLong(
2, shop_id.longValue());
preStmt.setString(
3,getTimeByCalendar());
preStmt.setLong(
4, user_id.longValue());
i=preStmt.executeUpdate();
}
catch (SQLException e)
{
e.printStackTrace();
}
return i;
//返回影响的行数,1为执行成功
}
//开始录入参数数据
public int insertPlocc(){
int i=
0;
return i;
}
}