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分区:基于属于一个给定连续区 ...
随机推荐
- [转]将Word转(保存)为带书签的PDF
提到的方法非常管用,感谢原作者的分享. 原文地址:http://blog.163.com/rongting_chen/blog/static/16490684420114266192887/ 将wor ...
- GL_GL系列 - 预算管理分析(案例)
2014-07-09 Created By BaoXinjian
- BIP_BI Publisher Administrator设定Configuration/Font/Currencies(案例)
2014-08-08 Created By BaoXinjian
- OAF_架构MVC系列1 - MVC的概述(概念)
2015-04-03 Created By BaoXinjian
- sublime 安装常用插件
1.先要安装Package Control ,ctr+` 打开控制台,复制安装脚本,脚本在https://packagecontrol.io/installation#st3获取. 2.安装插件,ct ...
- rsync 目录 斜杠
源: 不带:同步 目录和内容 带/: 只同步内容 target目录: 待. -Warv --delete -W, --whole-file copy files whole ( ...
- Delphi Alpha皮肤控件使用方法
//用于刷新控件颜色. FsSkinManager.BeginUpdate; FsSkinManager.EndUpdate(True); //动态选择皮肤 begin if not FIsswitc ...
- Gradle多渠道打包[umeng]
前言 国内Android应用市场品种太多,血统不纯,每次上线App都打包打到手软,上传上到吐血!好在我们有了Android studio和gradle,一条命令打包各种渠道版本App! 正文 Umen ...
- HDU 3535 【背包】
题意: 给出n组数据,每组数据有一个类型. 0代表至少选择一个,1代表至多选择一个,2代表任意选择. 给出背包容量. 如果背包不能满足最基本的要求输出-1. 思路: 背包问题变相考察~ 当0的时候初始 ...
- JQuery基础教程:选择元素(中)
自定义选择符 JQuery在各种CSS选择符的基础上还添加了独有的完全不同的自定义选择符,注意,只要可能,jQuery就会使用浏览器原生的DOM选择符引擎去查找元素.但在使用自定义选择符的时候,就无法 ...