MySQL 按日期分表
一、表不存在时则创建
之前做项目实在是太赶了,很多东西都没记录。是时候补回来了
MySQL做一个大表,由于要存历史记录,所以数据量很大,查询很慢。恰好查询的时候,又不需要时间太久的冷数据。现在将其实现原理提取成一个控制台小程序。
首先,创建一个简单的数据库访问类。
public static class CommonDao
{
private static MySqlConnection conn = new MySqlConnection(ConfigurationManager.AppSettings["DB"]); //创建连接 /// <summary>
/// Insert Update Delete语句的执行
/// </summary>
/// <param name="SQL">SQL语句</param>
/// <returns>返回影响行数</returns>
public static int ExecuteNonQuerySQL(string SQL)
{
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = SQL;
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
int Count = cmd.ExecuteNonQuery();
conn.Close();
return Count;
}
}
由于是按分钟分表,所以写个定时器,每一分钟往里面插入5条数据:
static void Main(string[] args)
{
//每分钟执行一次,插入5条数据
Timer t = new Timer();
t.Enabled = true; //到达时间就执行一次,或者是持续执行
t.AutoReset = true; //一直执行 t.Elapsed += (sender, eea) =>
{
for (int i = ; i < ; i++)
{
DateTime dt = DateTime.Now;
string TableName = "person" + dt.ToString("yyyyMMddHHmm");
string sql = "INSERT INTO " + TableName + " VALUES(null,'superman','" + dt.ToString("yyyy-MM-dd HH:mm:ss") + "')";
try
{
CommonDao.ExecuteNonQuerySQL(sql);
}
catch (Exception e)
{
MySqlException ex = e as MySqlException;
//1146的代号就是表不存在的错误
if (ex.Number == )
{
//如果表不存在,则先创建这个表
string SQLCreateTable = "CREATE TABLE " + TableName + " LIKE person"; //从模板表来创建新表,这样的好处是索引、自增什么的可以一次性建好
CommonDao.ExecuteNonQuerySQL(SQLCreateTable);
}
}
} }; Console.ReadKey();
}
第一张Person模板表的格式如下:
CREATE TABLE `person` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(255) DEFAULT NULL,
`OperateTime` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

于是就每分钟都会创建表并添加数据。

二、分表后跨表查询的问题
分表后有很多问题要处理,简单做两个,maybe会有其他问题。
1、数据在哪个表里;
2、数据跨表了,那么就需要表连接;
通常对这种大表,都肯定要加时间的了,所以要根据时间来判断查哪张表和如何表连接。
增加一个查询的方法:
/// <summary>
/// 根据SQL语句查询DataTable
/// </summary>
/// <param name="SQL">SQL语句</param>
/// <returns>返回DataTable</returns>
public static DataTable GetDataTableBySQL(string SQL)
{
DataSet ds = new DataSet();
MySqlDataAdapter Msda = new MySqlDataAdapter(SQL, conn);
Msda.Fill(ds);
DataTable dt = new DataTable();
if (ds.Tables.Count > )
{
dt = ds.Tables[];
}
return dt;
}
数据定位的方法:
public static string GetTableName(DateTime dtStart, DateTime dtEnd)
{
if(dtStart.ToString("yyyyMMddHHmm") == dtEnd.ToString("yyyyMMddHHmm"))
{
return "person" + dtStart.ToString("yyyyMMddHHmm");
}
else
{
string TableName = "(SELECT * FROM person" + dtStart.ToString("yyyyMMddHHmm");
DateTime dt = dtStart.AddMinutes();
while(dt.ToString("yyyyMMddHHmm") != dtEnd.ToString("yyyyMMddHHmm"))
{
TableName += " UNION ALL SELECT * FROM person" + dt.ToString("yyyyMMddHHmm");
dt = dt.AddMinutes();
}
TableName += " UNION ALL SELECT * FROM person" + dt.ToString("yyyyMMddHHmm") + ") AS T";
return TableName;
}
}
测试查询:
string sql = "SELECT * FROM " + GetTableName(Convert.ToDateTime("2016-04-21 17:54:00"),Convert.ToDateTime("2016-04-21 17:56:00"));
DataTable dt = CommonDao.GetDataTableBySQL(sql);
foreach(DataRow dr in dt.Rows)
{
Console.WriteLine(dr[] + " " + dr[] + " " + dr[]);
}
结果如下:

很明显上面的代码暴露出了一个问题,ID重复了。
本处提供的可选解决方案是。
1、ID使用GUID。
2、自增数字的前面加上表名的日期前缀,如,如果你是按月分表,自增Id设置long类型,然后起止值设置为"201604000000000000000 + Id"。这样就不会重复啦。
自定数字的方式只需多执行以下一条SQL语句:
ALTER TABLE person201604211757 AUTO_INCREMENT=2016042100;
然后生成的ID列的值如下:

简单示例就是如此
MySQL 按日期分表的更多相关文章
- MySql分区、分表和分库
MySql分区.分表和分库 数据库的数据量达到一定程度之后,为避免带来系统性能上的瓶颈.需要进行数据的处理,采用的手段是分区.分片.分库.分表. 一些问题的解释: 1.为什么要分表和分区? 日常开发中 ...
- MySQL订单分库分表多维度查询
转自:http://blog.itpub.net/29254281/viewspace-2086198/ MySQL订单分库分表多维度查询 MySQL分库分表,一般只能按照一个维度进行查询. 以订单 ...
- MyBatis实现Mysql数据库分库分表操作和总结
前言 作为一个数据库,作为数据库中的一张表,随着用户的增多随着时间的推移,总有一天,数据量会大到一个难以处理的地步.这时仅仅一张表的数据就已经超过了千万,无论是查询还是修改,对于它的操作都会很耗时,这 ...
- MySQL+MyCat分库分表 读写分离配置
一. MySQL+MyCat分库分表 1 MyCat简介 java编写的数据库中间件 Mycat运行环境需要JDK. Mycat是中间件.运行在代码应用和MySQL数据库之间的应用. 前身 : cor ...
- php面试专题---mysql数据库分库分表
php面试专题---mysql数据库分库分表 一.总结 一句话总结: 通过数据切分技术将一个大的MySQLServer切分成多个小的MySQLServer,既攻克了写入性能瓶颈问题,同一时候也再一次提 ...
- MySQL之分库分表
MySQL之分库分表(MyCAT实现) 分库分表介绍 随着微服务这种架构的兴起,我们应用从一个完整的大的应用,切分为很多可以独立提供服务的小应用.每个应用都有独立的数据库. 数据的切分分为两种: ...
- 使用ShardingSphere-JDBC完成Mysql的分库分表和读写分离
1. 概述 老话说的好:选择比努力更重要,如果选错了道路,就很难成功. 言归正传,之前我们聊了使用 MyCat 实现Mysql的分库分表和读写分离,MyCat是服务端的代理,使用MyCat的好处显而易 ...
- MySQL分区和分表
一.概念 1.为什么要分表和分区?日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询 ...
- mysql分区与分表的区别
分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中. mysql支持的分区类型包括Range.List.Hash.Key,其中Range比较常用: RANGE分区:基于属于一个给定连续区 ...
随机推荐
- PO_PO系列 - 收货管理分析(案例)
2014-07-01 Created By BaoXinjian
- Mobirise
网站建设器Mobirise v1.9.2 免费版 - 绿色软件联盟 2015年9月5日 - 网站建设器Mobirise是一个用户友好的程序,使您可以构建桌面和移动网站,准备在Javas cript中. ...
- bug_ _fragment_“The specified child already has a parent. You must call removeView"的解决以及产生的原因
这个异常的出现往往是因为非法使用了某些方法引起的. 从字面意思上是说这个特定的child已经有一个parent了,你必须在这个parent中首先调用removeView()方法,才能继续你的内容.这里 ...
- queue 与 vector
优先队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序 每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储. 例如:我们常用的操作就 ...
- Mac下的eclipse按住ctrl点击无法查看类文件
问题主要是项目的.project或者.build文件有问题,github上check的另一个项目就没有这样的现象,可以新建一个项目,然后把新建项目的这两个文件一一替换无法ctrl点击的项目中的文件. ...
- JAVA赋值运算符
赋值预算符,简单来说就是把以及定义了值的变量值赋值给刚定义的变量 例如,a学员,与b学员的成绩相同,a学员是80分,我们根据a学员的成绩,输出b学员的成绩. public class Test{ pu ...
- Mac 上SVN上传.a文件
SVN默认是忽略.a文件,所以修改配置文件去掉忽略配置行的 *.a 通过终端打开配置文件: open ~/.subversion/config 把下面两行(也可能是一行)中的注释和*.a去掉, #gl ...
- URL编码CFURLCreateStringByAddingPercentEscapes使用(ARC)
URL 编码:CFURLCreateStringByAddingPercentEscapes If you have tried to send any information using a GET ...
- [ActionScript 3.0] AS3.0 马赛克效果
var bmpd:BitmapData; var matrix:Matrix; var bmp:Bitmap; var size:Number = 5; /** * @author:Frost.Yen ...
- crm 4 UserHasRole
//获取当前人员是否含有指定角色权限 function UserHasRole(roleName) { //get Current User Roles, oXml is an object var ...