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分区:基于属于一个给定连续区 ...
随机推荐
- OkHttp 详解
OkHttp使用: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html OkHttp源码: http:/ ...
- spark on hive 配置hive的metastore为mysql
<property><name>hive.metastore.uris</name><value></value><descripti ...
- C++模板元编程 - 2 模仿haskell的列表以及相关操作
这是昨天和今天写的东西,利用C++的可变模板参数包以及包展开,模式匹配的一些东西做的,感觉用typename...比轮子叔那个List<A,List<B, List<C, D> ...
- Java多线程之线程结束清理
该事例说明了清理工作必须要放在finally块中 package Thread.Interrupting; import java.util.concurrent.TimeUnit; class Ne ...
- 线程中的wait() 与 锁的关系
我们先看一段代码: /** * 计算输出其他线程锁计算的数据 * */ public class ThreadA { public static void main(String[] args) th ...
- 最完美的xslt数值函数与字符串函数(转)
http://www.cnblogs.com/guoxu/articles/1744007.html 任何的编程语言或者是SQL语句都有内置的函数或方法,而强大灵活的xslt技术也是如此.熟练掌握XS ...
- vmware虚拟机挂起后无法再恢复(转)
之前一直使用vmware调试程序,但有一天它被挂起后,就一直无法恢复. 提示: 无法获取该配置文件上的排他锁 另一个VMware进程可能正在使用此配置文件. 后来在google里查了一下,发现其实是一 ...
- [Java] java中的异常处理-续
异常处理器,它由try, catch, finally以及随后的程序块组成.finally不是必须的. catch的括号有一个参数,代表所要捕捉的异常的类型.catch会捕捉相应的类型及其衍生类.tr ...
- delphi 调用百度地图WEBSERVICE转换GPS坐标 转
http://www.cnblogs.com/happyhills/p/3789864.html 百度地图的API说明 使用方法 第一步,申请密钥(ak),作为访问服务的依据: 第二步,按照请求参 ...
- java模拟用户登录(排除没有验证码情况下,抓取网页信息)
import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import j ...