从建房子说起
记得小时候,我爸,大伯,叔叔都是在祖屋里住着的,后来我爸和叔叔都在村子里建了房子,都搬出来了。这也是很顺理成章的事情,因为原有的祖屋已经不足以住下我们的一大家子人了。
不过,这时就会有一个问题,就是在不知情也没有其他信息的前提下,怎么根据姓名来判断他是住在祖屋还是新屋呢?最简单最笨的方法,当然是先在祖屋找,没找到就再到新屋找,但是新屋比较多或者两个屋子之间相距比较远的话,这个成本就变得很高,不合算。
为了降低这个成本,我们可以事先用一个本子(索引表)记录下每个人住在哪里,这样只要一查本子就知道了。
逐步分表
和房子不够就需要重新建一处房子一样,当一个数据表记录太多太大,从而影响了查询效率的时候,我们就应该考虑分表,把新增的数据都保存到另一个表上,依 次进行下去。和上面找人的问题一样,我们应该有一个什么样的策略来判断某个ID的记录在那个表上。这里有几种方式:
一:把记录ID和数据表名的对应关系保存在一个独立的表(找人问题中的本子)中,可是这样当记录很多的时候这个表的记录就会很多,虽然这个表结构很简单,但是也会影响到查询效率。还有就是在插入删除的时候都得关联这个表的操作,不方便。
二: 一次性把现有的所有数据根据某个字段(通常是ID)按照某种规则重新散列到各个表(包括新建的)上。这样原有程序改动不大(如果设计合理的话,可能改动的 只是一个配置的参数),而且每个表的访问压力相当(如果Hash规则足够随机的话),不过这一次性的数据迁移代价可能很高,有风险。
三:如果ID是一个自动自增主键,那么我们就可以把每个表的初始ID记录在配置文件里,这样我们的程序就很容易根据ID找到对应的数据表了。这种方法没有数据大规模迁移的麻烦,可是每个表的访问压力会有比较大的差别。
第一种显然是不能用的,第二种和第三种那种好点,就应该根据实际情况来确定(通常可能都是第三种好点)。
逐步分表的思想是在需要的时候,新增一个表,以保证查询效率。但是如果我们在系统设计的时候就可以对将来的数据量有一个比较准确的估计,我们就可以在一 开始的时候就设计N个分表,如果这个N值较大的话,最好独立成一个数据库。在插入数据的时候,我们根据记录ID把数据Hash到某个表上,这样在操作数据 的时候就可以根据ID来计算表名了。
这种做法很简单,省了很多功夫,不过需求并没有像预期的变化,原来的N值还是小了,这时就会比较麻烦,得执行逐步分表的步骤。而如果发现N值设置太大了, 这样就会导致数据表利用率太低,有点浪费了资源。(例如,在mysql中myisam类型的数据表,一个表对应三个文件,这样N值太大就是说文件过多了, 同样也会影响到效率)
分表带来的问题
对于很多的互联网应用,我们主要关注的是查询的优化(经常不惜以空间换时间),但是我们在查询的时候可能并不是只根据ID来查询,而且还通常需要分页。 我们上面的分表却无法胜任这些,所以我们得另外想办法,例如把结果缓存起来(如内存表,文件,APC,Memcache等)。不过不管怎么缓存,总感觉有 点别扭,不够完美。
假如有这样三个对象表:用户表,影片表和Tag表,他们各自对应的主键ID为:user_id,movie_id和tag_id,他们两两之间的对应关系 是多对多的(例如一个用户可以收藏多个影片,可以为每个收藏的影片填写多个tag)。现在要做的就是可以根据其中的任一个对象来迅速查找其它两个对象的相 关信息,数据表结构应该怎么样设计?
如果每次只是对一种ID进行分表,显然我们要建立三种散列表,如果考虑把散列表独立成库的话,就得用三个数据库,管理和操作都有一定的麻烦。后来灵光一 闪,想到了一种比较好的解决方法:表中除了保存user_id,movie_id和tag_id外,另外加了一个flag字段,这四个字段组成组合主键 (当然表还可以保存其他的信息,特别适合保存一些统计信息,排序的时候很有用)。其中flag字段标志此记录是根据哪种ID进行散列的,不妨设 flag=1时根据user_id散列,flag=2时根据movie_id散列,flag=3时根据tag_id散列。
这时假如我们要根据movie_id查找关联的用户和tag_id,这时我们的where条件可以这样写:
SELECT * FROM {$table} WHERE movie_id='{$movie_id}' AND flag='2' ...
(注:假设我们根据movie_id的值计算得到相应的Hash表名为$table,实际上这也是很容易得到的。)
其他的两种也一样,这显然对查询很有利。当然这样设计之后,对数据的增删改操作就有点麻烦了(通过把对散列表的操作封装在一个类里面可以减少很多麻烦),不过为了查询效率的提升,这种牺牲应该还是值得的。
一些思考
接触关系数据库越多,就越发现关系数据库也有不少的局限,例如在查询效率和并发连接数方面,关系数据库通常会比key-value型数据库(例如 MemcacheDB,Tokyo Tyrant,Bigtable等)差很多,而且key-value型数据库很容易和Memcache结合,以实现持久化存储,从而很容易做到分布式存 储。也许以后会有人考虑开发一种专门存储JSON格式的数据库,呵呵~
还有就是,以前觉得Mysql很小,相比那些SQL Server,甚至oracle等等,但是现在觉得Mysql已经很庞然大物了,于是有人要给mysql瘦身,弄了个Drizzle出来。(就像我们觉得 apache已经是庞然大物了,所以我们弄了很多轻量级的服务器,如Lighthttpd,Nginx等,来实现相应特定的功能)
当然,所有的这些并不是说关系数据库已经“死了”,而只是细化了分工,从而弥补了关系数据库某些方面的不足。
相关推荐
分表是个目前算是比较炒的比较流行的概念,特别是在大负载的情况下,分表是一个良好分散数据库压力的好方法。 首先要了解为什么要分表,分表的好处是什么。我们先来大概了解以下一个数据库执行SQL的过程: 接收到...
数据库Sharding的基本思想和切分策略
里面所有对于分表的思想就是,尽量让表文件大小达到最小化, 把内容与其它信息分开的好处就是可以让每个表的文件最小化,对数据库操作压力会减小. 这样保证每张表数据量很小,操作速度会快,而且可以搭配缓存,...
在之前的文章中,我介绍了分库分表的几种表现...同时,流行的分布式系统中间件(例如MongoDB、ElasticSearch等)均自身友好支持Sharding,其原理和思想都是大同小异的。在很多中小项目中,我们往往直接使用数据库自增特
JPA1.0和早期的H框架,其思想是将关系型数据库抽象为对象池,这极大的限制了本来非常灵活的SQL语句的发挥空间。而本质上,当我们调用某H框架的session.get、session.load、session.delete时,我们是想传递一个以...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
数据库技术是软件开发中的必备技能,咱们从数据库基本操作到掌握数据库设计的能力,层层深入学习数据库设计思想,一个软件项目的底层逻辑中,数据的存储结构是重中之重,因此,数据库技术也是面试中常被面试官拿来...
sharding jdbc 这个分库分表技术要解决的问题就是,随着数据量级的提升,物理硬件达到瓶颈,单表的性能优化也带来了瓶颈。 而数据量仍然要突破的难题。 这个问题的解决方案,其实就是一种分治的思想。用一句...