`
g21121
  • 浏览: 694710 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MySql分表优化

 
阅读更多

        随着大数据时代的来临,越来越大的数据量冲击着我们的系统,很多脆弱的系统在数据洪水的猛攻下早已不堪重负甚至垮掉。随着计算机硬件的飞速发展,千兆、万兆网卡,光纤,SSD硬盘,DDR4等等最新硬件的出现,计算机的硬件性能不再是我们系统优化的重要关注点,慢慢的我们发现现在的Web系统绝大多数性能的瓶颈都来自数据库。

        前置系统即使你提供再多的web应用服务器,买再好的负载均衡设备,接最快的骨干线路却仍被数据库底下的性能所“坑爹”,页面动不动就卡死,查询一条数据要很久....

        所以优化我们的数据库是最省钱也是最有效的方法,可以使我们的系统性能大幅度的提升,优化数据库的方法有很多,例如:采用SSD固态硬盘存储核心数据,增加数据库集群等等。下面我们要介绍的一种就是“分表”优化,这种优化相对简单,在数据库设计时期就可做到合理的规划。

        分表优化简单的来讲就是将“大表”拆分成“小表”,这里的“大”有两个维度的意思:

        表字段水平维度:表字段多,一个表甚至有几十个字段。

        表内容垂直维度:表数据量大,几百万,几千万甚至上亿条数据。

        所以分表优化会从两个方向同时进行,垂直和水平。

 

        一般来说我们执行一条SQL语句是按以下顺序进行的:

        1.客户端将SQL通过连接发送的数据库服务器。

        2.数据库服务器对SQL语句进行解析并做一系列处理。

        3.执行SQL语句。

        4.将执行结果返回给客户端。

        期间诸如updae,delete等操作会造成一定程度上的“锁”,根据引擎不同,隔离级别设置不同可能会出现“锁字段”,“锁行”,“锁表”甚至“锁据库”等等情况。

        这样带来的后果就是SQL执行时间长,查询队列中等待的SQL无法继续进行,从而造成系统操作时间大幅度增加等不良后果。

        应对“锁”我们就需要合理的分表了。

 

        下面我们就先来研究“垂直分表”:

        据说MySQL可以支持1000个字段,然而往往我们是用不了也不建议用这么多的,一般情况下建议字段总数不要超过30个,10-20个比较合理,再多的话在关联查询时会造成效率上的浪费。当然这也不是绝对的,可以根据项目及具体情况来执行。

        以下是一张用户表,仅作为举例使用,不必去考虑其具体设计及内容合理性:


        以下是建表SQL语句: 

 

CREATE TABLE `USER` (
  `USR_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
  `NAME` varchar(20) DEFAULT NULL COMMENT '姓名',
  `LOGIN_NAME` varchar(64) NOT NULL COMMENT '登录名',
  `PASSWD` varchar(64) NOT NULL COMMENT '密码',
  `CUSTORM_ID` int(11) DEFAULT NULL COMMENT '客户代码',
  `STATUS` int(11) DEFAULT NULL COMMENT '用户状态',
  `SAFE_QUESTION` int(11) DEFAULT NULL COMMENT '安全提示问题',
  `SAFE_ANSWER` varchar(32) DEFAULT NULL COMMENT '安全提示答案',
  `CREATE_DATE` datetime DEFAULT NULL COMMENT '创建日期',
  `ACTIV_CODE` varchar(32) DEFAULT NULL COMMENT '激活码',
  `USR_TYPE` int(11) DEFAULT NULL COMMENT '用户类型',
  `MOBILE` int(15) DEFAULT NULL COMMENT '手机',
  `QQ` int(15) DEFAULT NULL COMMENT 'QQ',
  `ADDRESS` int(150) DEFAULT NULL COMMENT '联系地址',
  `AGE` int(10) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`USR_ID`)
);

 

        这个表内容信息丰富可以很全面的查询出所有的用户信息,既然如此我们还有必要利用分表去优化它吗?答案是肯定的,有必要!

        在访问量不大的情况下把所有信息都放置到一张表中可以很容易的获取所有信息,给我们代码的开发带来了极大的便利,但是一旦用户量激增,这种表结构就会产生很严重的诟病,例如:登录和更新用户信息同时进行,很容易导致锁表,相互影响;又如修改密码和修改其他信息也会如此等等。为了应对未来这种高并发的情况我们就应该合理的去设计库表了。

        首先,我们可以将用户安全相关信息提取出来,如:密码,登录名,安全提示问题,安全提示答案。将这些信息组成一个名为“PASSWD”的表,这样做的好处是:将登录及相关安全信息独立出来以供功能单一如“登录”的业务调用,这样就可以减轻一部分表的压力,登录时只到“PASSWD”查询即可完成操作,当有必要时再去查询其他信息,这样做也有另一个好处,就是可以将PASSWD的查看及修改权限固定,仅限一定的mysql用户可以操作以提升安全性。

        其次,我们将用户的相关联系信息提取,如:姓名,联系地址,年龄,手机,QQ。这些信息组成一个名为“USER_INFO”的表,这样我们就可以很方便的去扩展此表的字段及信息,更利于日后的更新及维护。

        最后,剩下的字段组成新的“USER”表,此表只负责存储与用户业务相关的字段,使得“USER”表能更好的贴近相关业务,这三张表通过字段“USR_ID”进行关联。

 

        分完后的表如下:



        建表SQL语句:

CREATE TABLE `USER` (
  `USR_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
  `CUSTORM_ID` int(11) DEFAULT NULL COMMENT '客户代码',
  `STATUS` int(11) DEFAULT NULL COMMENT '用户状态',
  `CREATE_DATE` datetime DEFAULT NULL COMMENT '创建日期',
  `ACTIV_CODE` varchar(32) DEFAULT NULL COMMENT '激活码',
  `USR_TYPE` int(11) DEFAULT NULL COMMENT '用户类型',
  PRIMARY KEY (`USR_ID`)
);

CREATE TABLE `PASSWD` (
  `USR_ID` int(11) NOT NULL COMMENT '用户编号',
  `LOGIN_NAME` varchar(64) NOT NULL COMMENT '登录名',
  `PASSWD` varchar(64) NOT NULL COMMENT '密码',
  `SAFE_QUESTION` int(11) DEFAULT NULL COMMENT '安全提示问题',
  `SAFE_ANSWER` varchar(32) DEFAULT NULL COMMENT '安全提示答案'
);

CREATE TABLE `USER_INFO` (
  `USR_ID` int(11) NOT NULL COMMENT '用户编号',
  `NAME` varchar(20) DEFAULT NULL COMMENT '姓名',
  `ADDRESS` int(150) DEFAULT NULL COMMENT '联系地址',
  `AGE` int(10) DEFAULT NULL COMMENT '年龄',
  `MOBILE` int(15) DEFAULT NULL COMMENT '手机',
  `QQ` int(15) DEFAULT NULL COMMENT 'QQ'
);

  

        当然以上分表并不是绝对的,可以根据具体情况去考虑分配方法及实现,我在这里只是提供一个思路,不必去严格要求上述分法的合理性,仁者见仁智者见智。

        总结:垂直分表适合字段较多且业务关联较多的情况,将这些字段分散到不同业务相关的表中分别维护,这样不同的业务之间不会相互影响或制约。

 

        另一种分表方式就是“水平分表”:

        垂直分表应用于字段,水平分表就应用于表内容了。

        我们知道一旦表内容非常多的时候查询起来就会很慢,虽然建立索引可以减少查询时间,但这毕竟不是根本解决办法。虽然MySQL没有硬性限制单表的大小,但是任何人都知道“表容量是不能无限制的增长的,这样影响性能”。

        我们可以在SQL控制台输入命令“SHOW TABLE STATUS”来查看表的大小及状态。

 

        水平分表的思路其实就是将一个内容高负荷的表拆分成一些小表以提高性能,如:论坛表结构。

        众所周知一个论坛对应了很多子论坛,子论坛又对应了很多帖子,帖子又对应了很多回复,结构如:

论坛 < 子论坛 forum < 帖子 topic < 回复 reply

        我们就可以forum按论坛id进行区分,如:forum_001,forum_002,forum_003....

        查询时我们利用特定算法拼接表名来进行操作。

        当然这是一种比较极端的做法,这种做法局限性也很强,一旦表结构修改将产生令人恐怖的修改工作量,水平分表类似于“分区分表”,我们会在接下来学习分区分表相关内容。

        水平分表优先需要解决“主键”问题,当全部数据集中在同一张表中时,我们可以利用MySQL的内部机制auto_increment 很轻易的实现主键自增,但是水平分表后每一张表都各种维护一份主键生成策略,这样就会产生重复冲突的现象,所以我们分表之前首先需要解决主键的生成问题。

 

        以下是几种解决方案:

        1.设置主键起始值

        加入我们已经将表水平分成了3张表,TABLE1,TABLE2,TABLE3,每张表容纳10万份数据,那么TABLE1 的主键范围就应该是1-10万,而TABLE2 主键范围则为10万1-20万,TABLE3 主键范围则为20万1-30万,依次类推。

        我们在创建表的时候可以手动的指定每张表主键增长的起始值,如TABLE1 起始值为1,TABLE2 为100001,TABLE3 为200001...

        建表语句则为:

CREATE TABLE `TABLE1` (
...
) AUTO_INCREMENT=1

CREATE TABLE `TABLE2` (
...
) AUTO_INCREMENT=100001

CREATE TABLE `TABLE3` (
...
) AUTO_INCREMENT=200001

        在建表时人为指定主键起始值的做法简单明了,维护成本小,不必额外关注主键生成问题。 但是在建表时直接声明起始值的做法有些生硬,我们可以将建表语句与主键设置语句分离,这样维护起来更加方便灵活:

CREATE TABLE `TABLE1` (
...
)
alter table `TABLE1` AUTO_INCREMENT=1

CREATE TABLE `TABLE2` (
...
)
alter table `TABLE2` AUTO_INCREMENT=100001

CREATE TABLE `TABLE3` (
...
)
alter table `TABLE3` AUTO_INCREMENT=200001

        sql语句的大概意思应该明白了吧,里面的错误就不必较真了。 

 

        2.利用拼接方式

        这种方式下我们不必为每张表维护不同的主键ID,每张表完全可以都是从1-10万相同即可,在使用表数据时需要程序中人为加入另一个标识符,如表名:

主键:TABLE1_1001 代表TABLE1中的1001数据
主键:TABLE2_1001 代表TABLE2中的1001数据

        这样做的好处就是建表时全部采用相同的条件语句,不必单独维护主键异同,使用时需要在程序中动态的去判断该数据所属的表即可。

        如主键ID显示可以变成1_1001,2_1001等等,将表和数据的ID分离。

 

        3.利用外部实现

        也就是在程序或一张单独的表中维护主键的值,在每次插入时取一下主键值。

  • 大小: 8.5 KB
  • 大小: 13.8 KB
  • 大小: 14.7 KB
分享到:
评论
2 楼 shochocinn 2013-07-11  
1 楼 g21121 2013-07-09  

相关推荐

    Node.js 实现的 MySQL 分表分库中间件,用于海量数据的分布式集群储存管理和高并发访问。.zip

    本文将深入探讨基于Node.js实现的MySQL分表分库中间件,它在分布式集群环境中起到至关重要的作用。 首先,Node.js是一种流行的JavaScript运行环境,它允许开发人员使用JavaScript进行服务器端编程。Node.js的异步非...

    mysql分表分库demo

    MySQL 分表分库 Demo MySQL 分表分库是指将大型数据库表分割成多个小表,以提高数据库的性能和可扩展性。随着业务数据的增长,数据库表中的数据不断增加,如果不加以控制,数据库的性能将会下降,影响业务的发展。 ...

    Python+MySQL分表分库实战

    MySQL分库分表是数据库架构设计中用于处理大规模数据量以及高并发请求的一种技术手段。通过将数据拆分到不同的数据库服务器中,能够有效降低单个数据库的负载,提高系统的扩展性和性能。Python作为一种流行的编程...

    mysql分表创建

    总之,MySQL分表是应对大数据挑战的有效手段,它涉及到数据库设计、性能优化等多个方面。通过合理分表,不仅可以提高查询速度,还能改善系统的可扩展性和可用性。在实际应用中,结合源码和工具,可以根据业务需求...

    Python与MySQL分表分库实战

    本篇文章将深入探讨"Python与MySQL分表分库实战"这一主题,帮助你理解如何有效地利用这两种技术来优化数据库性能和处理大数据。 首先,我们需要理解“分表分库”这一概念。随着数据量的增长,单一数据库可能会面临...

    Python+MySQL分表分库实战 - v1.0 - 运维生存时间 -(2016).mobi

    Python后端运维工程师的可靠参考书,重点介绍如何优化mysql数据库性能。

    Mysql分表查询,哈希,范围,列表

    【MySQL分表查询】在大型数据库系统中,随着数据量的不断增长,单表的数据规模可能会变得非常庞大,导致查询效率下降,系统性能受到影响。此时,分表技术就显得尤为重要。MySQL提供了多种分表策略,如哈希分表、范围...

    Mysql千万级别水平分表优化

    方案一:使用myisam进行水平分表优化 方案二:使用mysql分区优化 一:Myisam水平分区 1、创建水平分表 user_1: -- 创建水平分表 create table user_1( id varchar(50) PRIMARY key COMMENT '主键id', user_name ...

    mysql 分库分表查询工具-shard.zip

    MySQL 分库分表查询工具——Shard 在大型的互联网应用中,数据库的性能瓶颈往往成为系统扩展性的关键因素。为了应对高并发、大数据量的挑战,MySQL 数据库的分库分表策略被广泛采用。分库是将数据分散到多个独立的...

    PHP操作mysql数据库分表的方法_.docx

    当数据量达到一定规模,例如超过100万条记录,性能问题就会显现,此时就需要采取相应的优化策略,如分表或分区。本文主要讨论如何使用PHP操作MySQL数据库进行分表。 分表是一种常见的数据库扩展策略,它通过将一个...

    基于hibernate的mysql分表分库实例-mysql-cluster-hibernate.zip

    "基于hibernate的mysql分表分库实例-mysql-cluster-hibernate.zip"这个压缩包文件提供了一个具体的解决方案,它涉及到Hibernate ORM框架与MySQL数据库集群的整合,旨在处理高并发、大数据量的业务场景。 **...

    mysql性能优化教程.pdf (by caoz)

    ### MySQL性能优化知识点详解 #### 一、背景及目标 - **目的**:厦门游家公司(4399.com)为了提升员工技能水平,制定了这份MySQL性能优化教程,旨在为已有一定MySQL使用经验的工程师提供实战指导。 - **适用场景*...

    MySQL分库分表技术

    **MySQL分库分表技术** 随着互联网业务的快速发展,数据量呈现爆炸性增长,单个数据库的性能瓶颈问题日益突出。在这种背景下,MySQL的分库分表技术应运而生,旨在解决高并发、大数据量场景下的性能挑战。本篇将深入...

    mysql分表分库-mysqlfenbaiofenku.zip

    MySQL 分表分库是数据库优化和扩展的一种策略,主要用于处理大数据量、高并发场景下的数据库性能问题。在大型互联网应用中,随着用户数量和数据规模的增长,单个数据库可能无法承受大量的读写操作,这时就需要采取...

    Mysql分表分库-core-dbshard2.zip

    "Mysql分表分库-core-dbshard2.zip" 文件可能包含了一个名为 "core-dbshard2-master" 的项目,这个项目很可能是关于MySQL数据库分库分表的实现方案或工具。 分库分表是一种水平扩展(Scaling Out)的方式,当单个...

    一个MySQL分库分表php类

    一个MySQL分库分表php类。当一个表数据记录过大时就会出现性能瓶颈,而一般对应的解决办法是要么做分区表,要么分表,分区表就不说了,分表又分为垂直分割和水平分割,具体区 别请自行搜索。一般而言,分库分表属于...

    MySQL 分库分表的实现原理及演示案例

    MySQL分库分表是一种数据库架构优化技术,其目的是为了提高大型数据库系统的性能和可扩展性。在面对大规模数据和高并发访问时,单库单表往往难以满足需求,分库分表就成为了必要之选。分库分表技术可以将数据分散...

Global site tag (gtag.js) - Google Analytics