【引自ttystar的博客】前言:在上一章介绍了MySQL的优化和优化思路,所以如果出现数据库已经建立索引的情况,在使用的时候sql语句索引查询;但是在慢查询日志中,还是发现之前的sql语句:1):sql语句的索引没有作用,2):查询的数据量太大,数据的查询速度慢。在工作过程中,每个数据库都会有海量的数据。比如访问量大了会导致数据的查询变慢。那么如何解决这个问题呢,我们往下看:分区和分表:我们的数据库数据越来越大,其次是单表数据太多。导致查询读取变慢,而且由于表的锁机制,应用操作也受到严重影响,出现数据库性能瓶颈。1.分表什么是分表?分表就是将一张大表按照一定的规则分解成多个具有独立存储空间的实体表。每个表对应三个文件,MYD数据文件,.MYI索引文件,.frm表结构文件。这些表可以分布在同一个磁盘上,也可以分布在不同的机器上。App在读写时,根据预先定义的规则获取对应的表名,然后进行操作。主要针对myisam存储,如果是innodb存储,那么就是.idb文件和.frm文件将单个数据库表拆分成多个数据表,然后在用户访问的时候,按照一定的算法(比如使用hash也可以采用求余(取模)的方式,让用户访问不同的表,从而将数据分散到多个数据表中,减少单个数据表的访问压力,提高数据库访问性能。目的分表是为了减轻数据库的负担,缩短查询时间。注意:客户端访问时,并不知道表已经被分表了。它仍然属于一个逻辑整体。对于客户端来说,客户端主要是关心查询的内容和查询的速度效率,但是作为一个DBA要理解这些;只有这样才能满足客户的要求。另外还有两种拆分方式:垂直拆分和水平拆分分裂:垂直拆分是指对数据表的列进行拆分,将一个列数较多的表拆分为多个表。水平拆分是指数据表拆分。行拆分,将一个表中的数据拆分到多个表中存储。分表的方式:1)mysqlcluster不分表,但起到分表的作用。集群可以分担数据库操作的数量,将任务分发给多个数据库。集群可以实现读写分离,降低读写压力。从而提高数据库性能。2)预先估计会有一个数据量大,访问频繁的表,分成若干个表。比如娱乐新闻类APP,可以通过每分钟的访问次数,计算出每小时、每天的大概访问情况,如果是这样的话,那么我们把这些数据存储在分表中,比如创建10000张表,设置阈值,当某一数据量达到预设值时,我们要存储下一张表中的内容以保证数据库的性能。3)使用合并存储引擎实现分表。对于DBA来说,分离现有的大数据表是一件痛苦的事情。最痛苦的是改代码,因为程序中的sql语句已经写好,使用merge存储引擎来实现分表,比较合适。然后介绍一下merge的用法和作用:merge存储引擎:合并子表,分为主表和子表,主表类似于一个壳,逻辑上封装了子表,其实就是数据存储在子表中间。注意:Word表格用于存储真实数据,不能细分,但可以合并。如果要创建多个单词表,在创建之初就多创建几个,估计需要多少个。我们可以通过主表插入和查询数据,如果知道分表的规则,我们也可以直接操作分表。然后我们来做一个merge的演示,希望大家对merge有更深的理解建立一个完整的表来存放所有的成员信息(表名是tty)mysql>dropdatabaseIFEXISTStest;=======>Iftestexiststhendeleteitmysql>createdatabasetest;=========>createtestdatabasemysql>usetest;==========>entertestlibrarycreatetabletty(===============>createttytableidbigintauto_increment主键,=============>设置id号为主键namevarchar(20),=============>namecharactertypesextinyintnotnulldefault'0'==========>性别字符类型)engine=myisamdefaultcharset=utf8auto_increment=1;============>存储引擎为myisam,utf-8字符集,可自动扩展。接下来,向其中添加一些数据:mysql>insertintotty(name,sex)values('tom1',1);mysql>insertintotty(name,sex)selectname,sexfromtty;多次执行第二条语句,会得到很多数据执行完我们来看一下有多少条数据:mysql>select*fromtty;{共有8192条数据}接下来我们分表。这里我们把tty分成两个表tb_tty1和tb_tty2。创建tb_tty1表:mysql>usetest;DROPtableIFEXISTStb_tty1;createtabletb_tty1(idbigintprimarykey,namevarchar(20),sextinyintnotnulldefault'0')ENGINE=MyISAMDEFAULTCHARSET=utf8;DROPtableIFEXISTStb_tty2;createtabletb_tty2(idbigintprimarykey,namevarchar(20),sextinyintnotnulldefault'0')ENGINE=MyISAMDEFAULTCHARSET=utf8;Createtb_tty2table//创建tb_tty2也可以像tb_tty1一样使用如下语句createtabletb_tty2;创建主表tb_ttyDROPtableIFEXISTStb_tty;注意:INSERT_METHOD,这个参数INSERT_METHOD=NO表示该表不能用于任何写操作,INSERT_METHOD=LAST表示插入到最后一个表中。INSERT_METHOD=first表示插入到第一个表中。查看tb_tty表、tb_tty1、tb_tty2的结构:mysql>desctb_tty;接下来,我们将数据分成两个子表:mysql>insertintotb_tty1(id,name,sex)selectid,name,sexfromttywhereid%2=0;mysql>insertintotb_tty2(id,name,sex)selectid,name,sexfromttywhereid%2=1;如果分三张表,可以用id%3=0,id%3=1,id%=2查看两个子表表的数据:{一共8192条数据如前所述注:总表只是一个壳,数据访问发生在各个子表中。注意:每个子表都有自己独立的关联表文件,而主表只是一个壳,没有完整的关联表文件2.分区什么是分区?分区和分表类似,都是按照规则分解表。不同的是,分表是将一张大表分解成若干个独立的实体表,而分区则是将数据切分成段存储在多个位置。分区后,表还是一张表,只是数据散列到多个位置。此外,分区还可以分为垂直分区和水平分区两种。属性仍然保持。垂直分区(VerticalPartitioning)这种分区方式一般是通过对表进行垂直分区来减小目标表的宽度,从而将一些特定的列分成特定的分区,每个分区包含其中的所有列。对应的行。检查配置是否支持分区:mysql>showplugins;在显示的结果中,可以看到分区是ACTIVE,说明支持分区。在演示分表的方法之前,接下来先演示一个分区的方法:mysql>createdatabasetest2;mysql>usetest2;mysql>createtableifnotexistsuser(idintnotnullauto_increment,namevarchar(30)notnulldefault'',sexint(1)notnulldefault'0',primarykey(id))defaultcharset=utf8auto_increment=1partitionbyrange(id)(partitionp0valueslessthan(3),partitionp1valueslessthan(6),partitionp2valueslessthan(9),partitionp3valueslessthan(12),partitionp4valueslessthanmaxvalue);插入一些数据(名称,性别)值('tom3','1');mysql>insertintotest2.user(名称,性别)值('tom4','0');mysql>insertintotest2.user(名称,性别)值('tom5','0');mysql>insertintotest2.user(name,sex)values('tom6','1');mysql>insertintotest2.user(name,sex)values('tom7','1');mysql>insertintotest2.user(name,sex)values('tom8','1');mysql>insertintotest2.user(name,sex)values('tom9','1');mysql>insertintotest2.user(name,sex)values('tom10','1');mysql>insertintotest2.user(name,sex)values('tom11','1');mysql>insertintotest2.user(name,sex)values('tom12','1');mysql>insertintotest2.user(name,sex)values('tom13','1');mysql>insertintotest2.user(姓名,性别)值('tom14','1');查看数据库表文件存放的地方通过命令:mysql>selectcount(id)ascountfromuser;从information_schema系统库中查询分区表中的分区信息查看分区信息mysql>select*fromtest2.userpartition(p0);添加一个新分区mysql>altertabletest2.useraddpartition(partitionpartionnamevalueslessthan(n));使用该命令时,需要p5新添加和删除的分区只能在删除后添加。当一个分区被删除时,该分区中的所有数据分区也被删除。下面的SQL将p1–p3合并为2个分区p01–p02mysql>altertabletest2.user->reorganizepartitionp1,p2,p3into->(partitionp01valueslessthan(8),->partitionp02valueslessthan(12)->);
