MYSQL千万级数据表,创建表及字段扩展的几条建议

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,性能是不好的,要用其它办法来解决这个问题。当然在正式项目中,具体情况还需要具体分析。

时间: 2024-12-12 16:49:58

MYSQL千万级数据表,创建表及字段扩展的几条建议的相关文章

提高mysql千万级数据SQL的查询优化30条总结

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0 3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用

Mysql千万级大表优化

Mysql的单张表的最大数据存储量尚没有定论,一般情况下mysql单表记录超过千万以后性能会变得很差.因此,总结一些相关的Mysql千万级大表的优化策略. 1.优化sql以及索引 1.1优化sql 1.有索引但未被用到的情况(不建议) (1)避免like的参数以通配符开头时 尽量避免Like的参数以通配符开头,否则数据库引擎会放弃使用索引而进行全表扫描. 以通配符开头的sql语句,例如:select * from t_credit_detail where Flistid like '%0'\G

30个MySQL千万级大数据SQL查询优化技巧详解

本文总结了30个mysql千万级大数据SQL查询优化技巧,特别适合大数据里的MYSQL使用. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t wher

Mysql千万级大数据查询优化经验 一点课堂(多岸学院)

提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意) 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0

千万级SQL Server数据库表分区的实现

千万级SQL Server数据库表分区的实现 2010-09-10 13:37 佚名 数据库 字号:T | T 一般在千万级的数据压力下,分区是一种比较好的提升性能方法.本文将介绍SQL Server数据库表分区的实现. AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验 最近使用SQL SERVER一个的缓存,数据量一天100w的速度增长,同时接受客户查询,速度由于数据量越来越大越来越慢,这里感谢  KillKill 和 邀约, 最近读了一套书不错,感兴趣的同学可以读读

数据引擎 创建表完整语法,字段类型,约束条件

数据引擎 创建表完整语法,字段类型,约束条件 回顾: 1.设置密码与修改密码 mysqladmin -uroot -p password设置的密码 mysqladmin -uroot -p原密码 password新密码 2.破解密码 - 1.先关掉服务,杀死进程 - 2.跳过权限认证启动服务端 - 3.以游客的身份登录即可 3.制作服务 - 1.mysql --install - 2.net start mysql 4.语法: 库的操作: 增: create database 库名; creat

MySQL 百万级分页优化(Mysql千万级快速分页)

以下分享一点我的经验 一般刚开始学SQL的时候,会这样写 : SELECT * FROM table ORDER BY id LIMIT 1000, 10; 但在数据达到百万级的时候,这样写会慢死 : SELECT * FROM table ORDER BY id LIMIT 1000000, 10; 也许耗费几十秒 网上很多优化的方法是这样的: SELECT * FROM table WHERE id >= (SELECT id FROM table LIMIT 1000000, 1) LIM

MySQL千万级多表关联SQL语句调优

本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使千万级表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果). 需要优化的查询:使用explain 出现了Using temporary: 有分页时出现了Using filesort则表示使用不了索引,需要根据下面的技巧来调整语句 rows过多,或者几乎是全表的记录数: key 是 (NULL): possible_keys 出现过多(待选)索引. 1.使用explain语法,对SQL进行

【优化】MySQL千万级大表优化解决方案

问题概述 使用阿里云rds for MySQL数据库(就是MySQL5.6版本),有个用户上网记录表6个月的数据量近2000万,保留最近一年的数据量达到4000万,查询速度极慢,日常卡死.严重影响业务. 问题前提:老系统,当时设计系统的人大概是大学没毕业,表设计和sql语句写的不仅仅是垃圾,简直无法直视.原开发人员都已离职,到我来维护,这就是传说中的维护不了就跑路,然后我就是掉坑的那个!!! 我尝试解决该问题,so,有个这个日志. 方案概述 方案一:优化现有mysql数据库.优点:不影响现有业务