从建房子说起
记得小时候,我爸,大伯,叔叔都是在祖屋里住着的,后来我爸和叔叔都在村子里建了房子,都搬出来了。这也是很顺理成章的事情,因为原有的祖屋已经不足以住下我们的一大家子人了。
不过,这时就会有一个问题,就是在不知情也没有其他信息的前提下,怎么根据姓名来判断他是住在祖屋还是新屋呢?最简单最笨的方法,当然是先在祖屋找,没找到就再到新屋找,但是新屋比较多或者两个屋子之间相距比较远的话,这个成本就变得很高,不合算。
为了降低这个成本,我们可以事先用一个本子(索引表)记录下每个人住在哪里,这样只要一查本子就知道了。
逐步分表
和房子不够就需要重新建一处房子一样,当一个数据表记录太多太大,从而影响了查询效率的时候,我们就应该考虑分表,把新增的数据都保存到另一个表上,依 次进行下去。和上面找人的问题一样,我们应该有一个什么样的策略来判断某个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等,来实现相应特定的功能)
当然,所有的这些并不是说关系数据库已经“死了”,而只是细化了分工,从而弥补了关系数据库某些方面的不足。
相关推荐
数据库分表处理是一种应对高负载环境下数据库压力的有效策略。在大数据量的情况下,单表操作可能导致锁表、阻塞,严重影响数据库性能和用户体验。为了解决这些问题,分表技术应运而生,通过将数据分散到多个表中,...
### 数据库分库分表(Sharding)技术详解 #### 一、基本概念与原理 **数据库分库分表(Sharding)**是一种常见的数据库优化技术,主要用于解决大规模数据存储和高并发访问带来的性能瓶颈问题。它通过将单一数据库...
水平切分的基本思想是将数据根据一定的规则分配到不同的数据库实例中。常见的水平切分算法有两种: 1. **范围法**:这是一种较为直观的切分方法,根据主键(例如`uid`)的值将其映射到特定的数据库实例上。例如,...
【大数据表的分表处理设计思想与实现】 在MySQL中,面对海量数据的存储和处理,单个表的规模过大可能会导致查询效率下降,甚至影响系统的稳定性和可用性。为了解决这一问题,分表设计成为了数据库优化的重要手段。...
数据分库分表是指将原始数据库中的数据分散存储到多个不同的数据库或表中,以此达到提高数据处理能力的目的。分库分表主要有两种形式:水平分库分表和垂直分库分表。本文着重讨论的是水平分库分表,即不改变表结构的...
### 数据库Sharding的基本思想和切分策略 #### 一、基本思想 **Sharding**,也称为数据库分片,是一种提高数据库性能和扩展性的技术手段。它的核心思想是将一个大型数据库分解成多个较小的部分(称为分片或shard)...
分库分表是数据库水平扩展的一种策略,它的核心思想是将一个大的数据库拆分成多个小的数据库,每个数据库负责一部分数据。这样可以分散数据存储和处理的压力,提高系统并发能力,避免单点故障,同时也能在一定程度上...
分表的基本思想是,将一个大的数据表根据一定的规则拆分成多个小的表,每个小表存储一部分数据。在本例中,使用了16张子表进行分表,这样做的目的是使得数据尽可能均匀地分布在各个表中,避免数据热点,减少查询时...
读写分离的基本思想是将数据库的读操作和写操作分配到不同的服务器上,以减轻主数据库的压力。在Yii中,可以自定义数据库连接配置来实现这一点。例如,你可以设置一个主数据库(用于写操作)和多个从数据库(用于读...
分库分表是一种常见的数据库水平扩展技术,其核心思想是将一个大表的数据分散到多个数据库或多个表中,以减轻单一数据库的压力,提升数据处理速度。 1. 分库:当单个数据库的负载过高时,可以通过将数据按照某种...
首先,描述中提到了分表的思想,这是为了减少单个表的数据量,使其保持在一个较小的范围内,从而加快查询速度。通过内容与其它信息的分离,可以创建更小、更专注的表,降低数据库的操作压力。例如,在一个论坛系统中...
因此,“分库分表”技术应运而生,这是一种有效的数据库水平扩展策略。本项目实战“分库分表数据看板”将深入探讨如何在实际操作中实施这一技术,以提升系统的处理能力和数据管理效率。 分库分表,顾名思义,就是将...
在之前的文章中,我介绍了分库分表的几种表现...同时,流行的分布式系统中间件(例如MongoDB、ElasticSearch等)均自身友好支持Sharding,其原理和思想都是大同小异的。在很多中小项目中,我们往往直接使用数据库自增特
其核心思想是将一个大表分成多个小表,分别存储在不同的数据库服务器上。 1. 水平分库:根据业务逻辑或用户群体,将数据分配到多个不同的数据库中,例如按照地域或部门进行划分。 2. 水平分表(Sharding):将一个...
分库分表是数据库水平扩展的一种方法,它的核心思想是将一个大表分为多个小表,分布在不同的数据库服务器上,以此来分散负载,提升查询效率。Ibatis在实现这一策略时,主要涉及以下几个关键点: 1. **分片规则**:...
Sharding-JDBC是Apache软件基金会下的开源项目,它的核心思想是在应用程序层面模拟数据库的分片功能,使得数据库横向扩展成为可能。该框架支持MySQL、Oracle、SQL Server等多种关系型数据库,且与Spring、MyBatis等...
JPA1.0和早期的H框架,其思想是将关系型数据库抽象为对象池,这极大的限制了本来非常灵活的SQL语句的发挥空间。而本质上,当我们调用某H框架的session.get、session.load、session.delete时,我们是想传递一个以...
### 分库分表shardingjdbc知识点详述 #### 一、简介 Apache ShardingSphere 是一个分布式的数据库中间件项目,旨在提供简单易用、高度可扩展的数据分片解决方案。ShardingSphere 支持多种模式,包括 JDBC 模式、...