十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
mysql分库分表一般有如下场景
创新互联公司是一家专注于成都网站设计、成都网站制作与策划设计,江安网站建设哪家好?创新互联公司做网站,专注于网站建设十余年,网设计领域的专业建站公司;建站业务涵盖:江安等地区。江安做网站价格咨询:18980820575
其中1,2相对较容易实现,本文重点讲讲水平拆表和水平拆库,以及基于mybatis插件方式实现水平拆分方案落地。
在 《聊一聊扩展字段设计》 一文中有讲解到基于KV水平存储扩展字段方案,这就是非常典型的可以水平分表的场景。主表和kv表是一对N关系,随着主表数据量增长,KV表最大N倍线性增长。
这里我们以分KV表水平拆分为场景
对于kv扩展字段查询,只会根据id + key 或者 id 为条件的方式查询,所以这里我们可以按照id 分片即可
分512张表(实际场景具体分多少表还得根据字段增加的频次而定)
分表后表名为kv_000 ~ kv_511
id % 512 = 1 .... 分到 kv_001,
id % 512 = 2 .... 分到 kv_002
依次类推!
水平分表相对比较容易,后面会讲到基于mybatis插件实现方案
场景:以下我们基于博客文章表分库场景来分析
目标:
表结构如下(节选部分字段):
按照user_id sharding
假如分1024个库,按照user_id % 1024 hash
user_id % 1024 = 1 分到db_001库
user_id % 1024 = 2 分到db_002库
依次类推
目前是2个节点,假如后期达到瓶颈,我们可以增加至4个节点
最多可以增加只1024个节点,性能线性增长
对于水平分表/分库后,非shardingKey查询首先得考虑到
基于mybatis分库分表,一般常用的一种是基于spring AOP方式, 另外一种基于mybatis插件。其实两种方式思路差不多。
为了比较直观解决这个问题,我分别在Executor 和StatementHandler阶段2个拦截器
实现动态数据源获取接口
测试结果如下
由此可知,我们需要在Executor阶段 切换数据源
对于分库:
原始sql:
目标sql:
其中定义了三个注解
@useMaster 是否强制读主
@shardingBy 分片标识
@DB 定义逻辑表名 库名以及分片策略
1)编写entity
Insert
select
以上顺利实现mysql分库,同样的道理实现同时分库分表也很容易实现。
此插件具体实现方案已开源:
目录如下:
mysql分库分表,首先得找到瓶颈在哪里(IO or CPU),是分库还是分表,分多少?不能为了分库分表而拆分。
原则上是尽量先垂直拆分 后 水平拆分。
以上基于mybatis插件分库分表是一种实现思路,还有很多不完善的地方,
例如:
第一阶段:
1,一定要正确设计索引
2,一定要避免SQL语句全表扫描,所以SQL一定要走索引(如:一切的 != 等等之类的写法都会导致全表扫描)
3,一定要避免 limit 10000000,20 这样的查询
4,一定要避免 LEFT JOIN 之类的查询,不把这样的逻辑处理交给数据库
5,每个表索引不要建太多,大数据时会增加数据库的写入压力
第二阶段:
1,采用分表技术(大表分小表)
a)垂直分表:将部分字段分离出来,设计成分表,根据主表的主键关联
b)水平分表:将相同字段表中的记录按照某种Hash算法进行拆分多个分表
2,采用mysql分区技术(必须5.1版以上,此技术完全能够对抗Oracle),与水平分表有点类似,但是它是在逻辑层进行的水平分表
第三阶段(服务器方面):
1,采用memcached之类的内存对象缓存系统,减少数据库读取操作
2,采用主从数据库设计,分离数据库的读写压力
3,采用Squid之类的代理服务器和Web缓存服务器技术
PS:由于篇幅问题,我只简单说一些基本概念,其实里面每个知识点关系到的内容都很多。特别是第一阶段,很多工作几年的程序员,都不能完全理解。我觉得要真正理解索引,最好的办法就是在1000W-亿级以上的数据,进行测试SQL语句,再结合 explain 命令进行查看SQL语句索引情况。
理论上是可以的,但效率上就有问题了,这么大量的数据一般不会放一张表里面,都会考虑分表,然后考虑索引、数据库主从、服务器配置等,提高查询效率php+mysql可以处理亿级的数据吗
1、使用用索引
注意有些情况下不能够使用索引来提高Order By语句的查询性能。
这里需要注意的是,并不是任何情况下都能够通过使用索引来提高Order Byz子句的查询效率。如对不同的关键字使用这个语句、混合使用ASC模式和DESC模式、用于查询条件的关键字与Order By语句中所使用的关键字不同、对关键字的非连续元素使用Order By子句、在同一条语句中使用不同的Order BY 和Group BY表达式、使用的表索引的类型不能够按顺序来保存行等情况,就无法通过使用索引来解决Order By语句的排序问题。此时就需要另想他法。如可以重新调整表结构或者查询语句,以满足使用这个特性的特定条件。
通常情况下,为了避免使用Order By语句导致的查询速度变慢的问题,先是需要考虑使用索引来解决问题。如果不能够通过索引来解决问题,那么可以通过缓存在一定程度来缓解。如可以增加soft_buffer_size变量的大小、根据实际情况调整Read_buffer_size变量的大小、更改tmpdir目录将其指向具有大量空闲空间的专用文件系统等等。有时候管理员可以使用这个特性将负载均匀分布到多个目录中去。
2、使用Explain关键字来确认是否可以通过索引来解决Order BY速度问题。
如可以通过使用explain select * from ad_user where is_active='Y' order by value(即在常规的查询语句前面加上一个explain关键字),用来判断是否可以使用索引来提高查询的效率。
判断的方法是:如果这个查询语句中,有一个using filesort这个字段,那么就非常的抱歉,无法通过使用索引来提高这个语句的查询效率。反之,没有这个字段,则说明可以通过索引来提高查询效率。
3、分页优化
分页程序原理很简单,这里就不多说了。
1.首先可以考虑业务层面优化,即垂直分表。
垂直分表就是把一个数据量很大的表,可以按某个字段的属性或使用频繁程度分类,拆分为多个表。
如有多种业务类型,每种业务类型入不同的表,table1,table2,table3.
如果日常业务不需要使用所有数据,可以按时间分表,比如说月表。每个表只存一个月记录。
2.架构上的优化,即水平分表。
水平分表就是根据一列或多列数据的值把数据行放到多个独立的表里,这里不具备业务意义。
如按照id分表,末尾是0-9的数据分别插入到10个表里面。
可能你要问,这样看起来和刚才说的垂直分表没什么区别。只不过是否具备业务意义的差异,都是按字段的值来分表。
实际上,水平分表现在最流行的实现方式,是通过水平分库来实现的。即刚才所说的10个表,分布在10个mysql数据库上。这样可以通过多个低配置主机整合起来,实现高性能。