mysql千万级数据表,创建表及字段扩展的几条建议
一:概述
当我们设计一个系统时,需要考虑到系统的运行一段时间后,表里数据量大约有多少,如果在初期,就能估算到某几张表数据量非常庞大时(比如聊天消息表),就要把表创建好,这篇文章从创建表,增加数据,以及字段扩展,这几个方面来给出建议。
二:创建表
假如现在我们需要创建IM项目中的聊天消息表,这个表数据量大,读操作远超过写操作,我们都知道,mysql常用的数据库引擎主要有innodb,myisam,这两个数据库引擎主要区别是,innodb支持事务,支持外键,锁是行级锁(行级锁只是针对主键,非主键也会锁全表),myisam不支持事务,不支持外键约束,锁是表级锁,从性能角度分析,myisam要比innodb更好一些,所以在数据库引擎上,我选择myisam,另外在消息发送用户id和消息接收用户id上加索引。
1:数据类型的选择
由于考虑到数据量非常大,所以在字段数据类型选择时,能用数字的就不要用字符串,当然时间类型也要用bigint来代替,不建议使用text类型,在varchar字段上建议创建默认值,比如:default '' ,因为where 使用 is null是全表扫描,数字类型也需要加默认值,比如 num int default 0,如果不加默认值,并且执行insert 语句,也没有对该字段赋值,哪么执行update xxx set num = num +1 时,你会发现sql不报错,然后num的值却没更新到,另外需要在作为条件查询的字段加索引.
2:表分区
在大数据面前,除了数据类型和性能有很大关系之外,我们还可以使用表分区,分表和分库目前还用不上,表分区概念
2.1 表分区概念
range分区:基于属于一个给定连续区间的列值,把多行分配给分区。
list分区:和range分区类似,区别是list分区是基于列值匹配一个离散值集合中的某个值来进行选择。
hash分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。
KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含>整数值。
可以使用SHOW VARIABLES LIKE '%partition%';来确定mysql支持的分区类型.
现在我使用range分区,分区字段是pk,完整sql语句如下
CREATE TABLE chatmsg(
cid bigint primary key,
cMsgSendUserId bigint,
cMsgReceiverUserId bigint,
cTime bigint,
cContent varchar(2000) not null default '',
cExt varchar(5000)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
PARTITION BY RANGE (cid) (
PARTITION p0 VALUES LESS THAN (1000000),
PARTITION p1 VALUES LESS THAN (5000000),
PARTITION p2 VALUES LESS THAN (1000000),
PARTITION p3 VALUES LESS THAN MAXVALUE
) ; create index senduserid_index on chatmsg(cMsgSendUserId);
create index receiverid_index on chatmsg(cMsgReceiverUserId);
create index ctime_index on chatmsg(ctime);
三:添加聊天记录。
从建表语句中看到,我们并没有使用外键,所以就需要手动检查外键约束的完整性。
select count(1) from user where uid = 消息发送者id
union all
select count(1) from user where uid = 消息接收者id
当上面的语句返回结果等于2时,才能执行添加语句。优化查询语句,可以参考我的这一篇文章:百万数据量优化方案
四:扩展字段
假如现在表已经产生了5千万条数据,产品经理过来说,小王,聊天记录需要加一个已读或未读的状态,如果此时在正式使用环境去alter tableadd column,可以想像这个操作有多耗时,有可能数据库直接崩溃都说不定,数据量大了,进行alter tableadd column操作数据库真崩溃过,不是危言耸听,还记得在建表的时候,我们创建了一个cExt字段,这个字段我们记录一个json 字符串,其实正确做法还要加一个版本号,这里我就没有加版本号。表里面的数据如下:
select cid,cTime,cContent,cext from chatmsg where cMsgSendUserId = 100 and cMsgReceiverUserId = 200
union ALL
select cid,cTime,cContent,cext from chatmsg where cMsgSendUserId = 200 and cMsgReceiverUserId = 100

这个方法能解决大部分扩展字段,查询出cext后,然后把该值转换为对像就可以。如果新增的字段,需要出现在where中,就需要根据实际情况进行分析了。
cext扩展字段优点:
(1)可以随时动态扩展属性
(2)新旧两种数据可以同时存在
(3)迁移数据方便,写个小程序将旧版本ext的改为新版本的ext,并修改version
cext扩展字段不足:
(1)cext里的字段无法建立索引
(2)cext里的key值有大量冗余,建议key短一些
五:其它
比如项目初期,产品经理说,小王,我选择任意两个用户,查询这两个人的聊天记录,需要返回这两个用户的昵称,产品经理选择两个用户,我们得到了这两个用户的id,如果直接chat表join user表,性能同样不好,这种情况我们可以考虑使用空间换时间,比如在聊天表中直接创建接收者和发送者的昵称。这个方法表达的意思是,大数据表尽量不要join,性能是不好的,要用其它办法来解决这个问题。当然在正式项目中,具体情况还需要具体分析。
我也会补充一些想法,如果文中有描述错误的地方,希望指出来,谢谢,欢迎大家发表自己的想法,大家共同进步。
mysql千万级数据表,创建表及字段扩展的几条建议的更多相关文章
- MySQL 千万级 数据库或大表优化
首先考虑如下因素: 1.数据的容量:1-3年内会大概多少条数据,每条数据大概多少字节: 2.数据项:是否有大字段,那些字段的值是否经常被更新: 3.数据查询SQL条件:哪些数据项的列名称经常出现在WH ...
- 提高mysql千万级数据SQL的查询优化30条总结
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- MySQL千万级数据JDBC插入
案例语句: String sql = "LOAD DATA LOCAL INFILE '" + dataFilepath + "' into table " + ...
- Mysql千万级大表优化
Mysql的单张表的最大数据存储量尚没有定论,一般情况下mysql单表记录超过千万以后性能会变得很差.因此,总结一些相关的Mysql千万级大表的优化策略. 1.优化sql以及索引 1.1优化sql 1 ...
- 如何优化MySQL千万级大表
很好的一篇博客,转载 如何优化MySQL千万级大表 原文链接::https://blog.csdn.net/yangjianrong1985/article/details/102675334 千万级 ...
- MySQL千万级大表优化解决方案
MySQL千万级大表优化解决方案 非原创,纯属记录一下. 背景 无意间看到了这篇文章,作者写的很棒,于是乎,本人自私一把,把干货保存下来.:-) 问题概述 使用阿里云rds for MySQL数据库( ...
- mysql循环插入千万级数据
mysql使用存储过程循环插入大量数据,简单的一条条循环插入,效率会很低,需要考虑批量插入. 测试准备: 1.建表: CREATE TABLE `mysql_genarate` ( `id` ) NO ...
- 千万级SQL Server数据库表分区的实现
千万级SQL Server数据库表分区的实现 2010-09-10 13:37 佚名 数据库 字号:T | T 一般在千万级的数据压力下,分区是一种比较好的提升性能方法.本文将介绍SQL Server ...
- mysql千万级测试1亿数据的分页分析测试
本文为本人最近利用几个小时才分析总结出的原创文章,希望大家转载,但是要注明出处 http://blog.sina.com.cn/s/blog_438308750100im0e.html 有什么问题可以 ...
随机推荐
- javaScript额外笔记
--------------------------------------------------------Part 1javascript:脚本语言辅助开发:网页的前台开发三大块:1.HTML ...
- Unity学习资料
前段时间刚简单接触下Spring.net,刚会简单注入,最近接手一项目确是用的Unity,网上找了一些很好的教程资料 算是入门了,高手已经写的很好了,我就转个链接吧: Unity V3 初步使用 —— ...
- (转)Ubuntu 12.04 中安装和配置 Java JDK
http://www.cnblogs.com/bluestorm/archive/2012/05/10/2493592.html 先去 Oracle下载Linux下的JDK压缩包,我下载的是jdk-7 ...
- 使用一个for循环将N*N的二维数组的所有值置1
<?php // 使用一个for循环将N*N的二维数组的所有值置1 $n = ; $a = []; ;$i<$n*$n;$i++){ $a[$i/$n][$i%$n] = ; } prin ...
- JAVASE 循环 之 计算各位上数字的和
问题:输入一个整数,计算它各位上数字的和 Scanner sc = new Scanner(System.in); int a = sc.nextInt(); int sum = 0; while(a ...
- phpcms v9 sql注入脚本
phpcms v9 SQL注入脚本 用法:python phpcms.py http://www.baidu.com import requests,sys,urllib url = sys.argv ...
- [OIDC in Action] 1. 基于OIDC(OpenID Connect)的SSO
在[认证授权]系列博客中,分别对OAuth2和OIDC在理论概念方面进行了解释说明,其间虽然我有写过一个完整的示例(https://github.com/linianhui/oidc.example) ...
- JAVAFX-4 开发应用
JavaFx 形状 Node类是所有JavaFX场景图形节点的基本基类.它提供了转换和应用效果到任何节点的能力. javafx.scene.shape.Shape类是Node类的子类.所有较旧的Jav ...
- Struts2超链接
Structs2中的<s:url>标签可以生成一个URL 地址,而且可以内嵌<s:param>标签,为URL指定请求参数. 具体属性有: action:可选属性,指定生成的 U ...
- 解决阿里云服务器3306端口无法访问的问题(windows server 2008r2)
3306端口一般是指mysql数据的默认端口.郁闷了几天的问题,远程无法连接服务器上的mysql服务.今天终于得到彻底解决. 首先,你要确保在服务器上安装好Mysql,并能本地启动.修改密码(如不知道 ...