一、表不存在时则创建

  之前做项目实在是太赶了,很多东西都没记录。是时候补回来了

  MySQL做一个大表,由于要存历史记录,所以数据量很大,查询很慢。恰好查询的时候,又不需要时间太久的冷数据。现在将其实现原理提取成一个控制台小程序。

  首先,创建一个简单的数据库访问类。

  1. public static class CommonDao
  2. {
  3. private static MySqlConnection conn = new MySqlConnection(ConfigurationManager.AppSettings["DB"]); //创建连接
  4.  
  5. /// <summary>
  6. /// Insert Update Delete语句的执行
  7. /// </summary>
  8. /// <param name="SQL">SQL语句</param>
  9. /// <returns>返回影响行数</returns>
  10. public static int ExecuteNonQuerySQL(string SQL)
  11. {
  12. MySqlCommand cmd = conn.CreateCommand();
  13. cmd.CommandText = SQL;
  14. if (conn.State != ConnectionState.Open)
  15. {
  16. conn.Open();
  17. }
  18. int Count = cmd.ExecuteNonQuery();
  19. conn.Close();
  20. return Count;
  21. }
  22. }

  由于是按分钟分表,所以写个定时器,每一分钟往里面插入5条数据:

  1. static void Main(string[] args)
  2. {
  3. //每分钟执行一次,插入5条数据
  4. Timer t = new Timer();
  5. t.Enabled = true; //到达时间就执行一次,或者是持续执行
  6. t.AutoReset = true; //一直执行
  7.  
  8. t.Elapsed += (sender, eea) =>
  9. {
  10. for (int i = ; i < ; i++)
  11. {
  12. DateTime dt = DateTime.Now;
  13. string TableName = "person" + dt.ToString("yyyyMMddHHmm");
  14. string sql = "INSERT INTO " + TableName + " VALUES(null,'superman','" + dt.ToString("yyyy-MM-dd HH:mm:ss") + "')";
  15. try
  16. {
  17. CommonDao.ExecuteNonQuerySQL(sql);
  18. }
  19. catch (Exception e)
  20. {
  21. MySqlException ex = e as MySqlException;
  22. //1146的代号就是表不存在的错误
  23. if (ex.Number == )
  24. {
  25. //如果表不存在,则先创建这个表
  26. string SQLCreateTable = "CREATE TABLE " + TableName + " LIKE person"; //从模板表来创建新表,这样的好处是索引、自增什么的可以一次性建好
  27. CommonDao.ExecuteNonQuerySQL(SQLCreateTable);
  28. }
  29. }
  30. }
  31.  
  32. };
  33.  
  34. Console.ReadKey();
  35. }

  第一张Person模板表的格式如下:

  1. CREATE TABLE `person` (
  2. `Id` int(11) NOT NULL AUTO_INCREMENT,
  3. `Name` varchar(255) DEFAULT NULL,
  4. `OperateTime` datetime DEFAULT NULL,
  5. PRIMARY KEY (`Id`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  

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

  

二、分表后跨表查询的问题

  分表后有很多问题要处理,简单做两个,maybe会有其他问题。

  1、数据在哪个表里;

  2、数据跨表了,那么就需要表连接;

  通常对这种大表,都肯定要加时间的了,所以要根据时间来判断查哪张表和如何表连接。

  增加一个查询的方法:

  1. /// <summary>
  2. /// 根据SQL语句查询DataTable
  3. /// </summary>
  4. /// <param name="SQL">SQL语句</param>
  5. /// <returns>返回DataTable</returns>
  6. public static DataTable GetDataTableBySQL(string SQL)
  7. {
  8. DataSet ds = new DataSet();
  9. MySqlDataAdapter Msda = new MySqlDataAdapter(SQL, conn);
  10. Msda.Fill(ds);
  11. DataTable dt = new DataTable();
  12. if (ds.Tables.Count > )
  13. {
  14. dt = ds.Tables[];
  15. }
  16. return dt;
  17. }

  数据定位的方法:

  1. public static string GetTableName(DateTime dtStart, DateTime dtEnd)
  2. {
  3. if(dtStart.ToString("yyyyMMddHHmm") == dtEnd.ToString("yyyyMMddHHmm"))
  4. {
  5. return "person" + dtStart.ToString("yyyyMMddHHmm");
  6. }
  7. else
  8. {
  9. string TableName = "(SELECT * FROM person" + dtStart.ToString("yyyyMMddHHmm");
  10. DateTime dt = dtStart.AddMinutes();
  11. while(dt.ToString("yyyyMMddHHmm") != dtEnd.ToString("yyyyMMddHHmm"))
  12. {
  13. TableName += " UNION ALL SELECT * FROM person" + dt.ToString("yyyyMMddHHmm");
  14. dt = dt.AddMinutes();
  15. }
  16. TableName += " UNION ALL SELECT * FROM person" + dt.ToString("yyyyMMddHHmm") + ") AS T";
  17. return TableName;
  18. }
  19. }

  测试查询:

  1. string sql = "SELECT * FROM " + GetTableName(Convert.ToDateTime("2016-04-21 17:54:00"),Convert.ToDateTime("2016-04-21 17:56:00"));
  2. DataTable dt = CommonDao.GetDataTableBySQL(sql);
  3. foreach(DataRow dr in dt.Rows)
  4. {
  5. Console.WriteLine(dr[] + " " + dr[] + " " + dr[]);
  6. }

  结果如下:

  

  很明显上面的代码暴露出了一个问题,ID重复了。

  本处提供的可选解决方案是。

  1、ID使用GUID。

  2、自增数字的前面加上表名的日期前缀,如,如果你是按月分表,自增Id设置long类型,然后起止值设置为"201604000000000000000 + Id"。这样就不会重复啦。

  自定数字的方式只需多执行以下一条SQL语句:

  1. ALTER TABLE person201604211757 AUTO_INCREMENT=2016042100;

  然后生成的ID列的值如下:

  简单示例就是如此

MySQL 按日期分表的更多相关文章

  1. MySql分区、分表和分库

    MySql分区.分表和分库 数据库的数据量达到一定程度之后,为避免带来系统性能上的瓶颈.需要进行数据的处理,采用的手段是分区.分片.分库.分表. 一些问题的解释: 1.为什么要分表和分区? 日常开发中 ...

  2. MySQL订单分库分表多维度查询

    转自:http://blog.itpub.net/29254281/viewspace-2086198/ MySQL订单分库分表多维度查询  MySQL分库分表,一般只能按照一个维度进行查询. 以订单 ...

  3. MyBatis实现Mysql数据库分库分表操作和总结

    前言 作为一个数据库,作为数据库中的一张表,随着用户的增多随着时间的推移,总有一天,数据量会大到一个难以处理的地步.这时仅仅一张表的数据就已经超过了千万,无论是查询还是修改,对于它的操作都会很耗时,这 ...

  4. MySQL+MyCat分库分表 读写分离配置

    一. MySQL+MyCat分库分表 1 MyCat简介 java编写的数据库中间件 Mycat运行环境需要JDK. Mycat是中间件.运行在代码应用和MySQL数据库之间的应用. 前身 : cor ...

  5. php面试专题---mysql数据库分库分表

    php面试专题---mysql数据库分库分表 一.总结 一句话总结: 通过数据切分技术将一个大的MySQLServer切分成多个小的MySQLServer,既攻克了写入性能瓶颈问题,同一时候也再一次提 ...

  6. MySQL之分库分表

    MySQL之分库分表(MyCAT实现)   分库分表介绍 随着微服务这种架构的兴起,我们应用从一个完整的大的应用,切分为很多可以独立提供服务的小应用.每个应用都有独立的数据库. 数据的切分分为两种: ...

  7. 使用ShardingSphere-JDBC完成Mysql的分库分表和读写分离

    1. 概述 老话说的好:选择比努力更重要,如果选错了道路,就很难成功. 言归正传,之前我们聊了使用 MyCat 实现Mysql的分库分表和读写分离,MyCat是服务端的代理,使用MyCat的好处显而易 ...

  8. MySQL分区和分表

    一.概念 1.为什么要分表和分区?日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询 ...

  9. mysql分区与分表的区别

    分区 分区就是把一个数据表的文件和索引分散存储在不同的物理文件中. mysql支持的分区类型包括Range.List.Hash.Key,其中Range比较常用: RANGE分区:基于属于一个给定连续区 ...

随机推荐

  1. [转]将Word转(保存)为带书签的PDF

    提到的方法非常管用,感谢原作者的分享. 原文地址:http://blog.163.com/rongting_chen/blog/static/16490684420114266192887/ 将wor ...

  2. GL_GL系列 - 预算管理分析(案例)

    2014-07-09 Created By BaoXinjian

  3. BIP_BI Publisher Administrator设定Configuration/Font/Currencies(案例)

    2014-08-08 Created By BaoXinjian

  4. OAF_架构MVC系列1 - MVC的概述(概念)

     2015-04-03 Created By BaoXinjian

  5. sublime 安装常用插件

    1.先要安装Package Control ,ctr+` 打开控制台,复制安装脚本,脚本在https://packagecontrol.io/installation#st3获取. 2.安装插件,ct ...

  6. rsync 目录 斜杠

    源: 不带:同步  目录和内容 带/: 只同步内容 target目录: 待. -Warv --delete -W, --whole-file            copy files whole ( ...

  7. Delphi Alpha皮肤控件使用方法

    //用于刷新控件颜色. FsSkinManager.BeginUpdate; FsSkinManager.EndUpdate(True); //动态选择皮肤 begin if not FIsswitc ...

  8. Gradle多渠道打包[umeng]

    前言 国内Android应用市场品种太多,血统不纯,每次上线App都打包打到手软,上传上到吐血!好在我们有了Android studio和gradle,一条命令打包各种渠道版本App! 正文 Umen ...

  9. HDU 3535 【背包】

    题意: 给出n组数据,每组数据有一个类型. 0代表至少选择一个,1代表至多选择一个,2代表任意选择. 给出背包容量. 如果背包不能满足最基本的要求输出-1. 思路: 背包问题变相考察~ 当0的时候初始 ...

  10. JQuery基础教程:选择元素(中)

    自定义选择符 JQuery在各种CSS选择符的基础上还添加了独有的完全不同的自定义选择符,注意,只要可能,jQuery就会使用浏览器原生的DOM选择符引擎去查找元素.但在使用自定义选择符的时候,就无法 ...