-
2019-02-22 21:43:06
在一些应用系统中数据库是要分库的,有些库主要的操作是写操作,使用分库可以降低数据库写的压力。但是读操作也是有的。在查询时是一些比较宽松的查询条件,其对应的数据可能分布在不同的数据库上,这个时候为了查询的方便,会构建一个表,叫索引表。这个索引表是存在另外的单独的一个数据库中,不会再分库了的。
更多相关内容 -
阿里巴巴中台战略--数据库分库分表之异构索引表
2019-03-03 23:48:53分库分表采用“**异构索引表**”的方式解决,即采用异步机制将原表的每一次创建或更新,都换另一个维度保存一份完整的数据表或索引表。这是另一种解决思路:拿空间换时间。阿里巴巴中台战略
- 阿里共享事业部的产生、演变和发展
- 企业信息中心发展的症结
- 共享服务体系
- 分布式服务框架的选择
- 共享服务中心建设原则
- 数据库瓶颈阻碍业务的持续发展
- 数据库分库分表
- 数据库分库分表之异构索引表
- 业务流程异步化和数据库事务异步化
- 阿里巴巴中台战略–事务与柔性事务
异构索引表
还是基于订单数据的分库分表场景,按照订单id取模虽然很好地满足了订单数据均匀地保存在数据库中,但在买家查看自己订单的业务场景中,就出现了全表扫描的情况,而且买家查看自己订单的请求是非常频繁的,必然给数据库带来扩展和性能的问题,有违“尽量减少事务边界”这一原则。
针对这类场景问题,最常用的是采用“异构索引表”的方式解决,即采用异步机制将原表的每一次创建或更新,都换另一个维度保存一份完整的数据表或索引表。这是另一种解决思路:拿空间换时间。
也就是应用在穿件或更新一条订单ID为分库分表键的订单数据时,也会再保存一份按照买家ID为分库分表键的订单索引数据,其结果就是同一买家的所有订单索引表都保存在同一数据库中,这就是给订单创建了异构索引表。
这时再来看看买家test1在获取订单信息进行页面展示时,应用对于数据库的访问流程就发生了如下图的变化。在有了订单索引表后,应用首先会通过当前买家id(以图中test1为例),
- 首先到订单索引表中搜索出test1的所有订单索引表(步骤1),
- 因为步骤2的sql请求中带了以buyer_id的分库分表键,所以一次是效率最高的单库访问,
- 获取到了买家test1的所有订单索引表列表并由DRDS返回到前端应用(步骤3和4),
- 应用在拿到返回的索引列表后,获取到订单id列表(1,5,8),
- 再发送一次获取真正订单列表的请求(步骤5),
- 同样在步骤6的sql语句的条件中带了分库分表键order_id的列表值,所以DRDS可以精确地将此SQL请求发送到对应订单id的数据库中,而不会出现全表扫描的情况。最终通过两次访问效率最高的sql请求代替了之前的需要进行全表扫描的问题。
这是有人可能会指出,为什么不是将订单的完整数据按照买家id维度进行一次分库保存,这样就只需要进行一次按照买家id维度进行数据库的访问就获取到订单的信息了?
这是一个好问题,其实淘宝的没订单数据就是在异构索引表中全复制的,即订单按照买家id维度进行分库分表的订单索引表跟以订单id维度进行分库分表的订单表中的字段完全一样,这样确实避免了多一次的数据库访问。但一般来说,应用可能会按照多个维度创建多个异构索引表,如果全部采用全复制的方法会带来大量的数据冗余,从而增加不少数据存储成本。
另外,在某些场景中,在获取主业务的列表时,可能需要依赖此业务表所在数据库的子业务表信息,比如订单示例中的主、子订单,因为是以订单id的维度进行分库分表,所以该订单相关的子订单、订单明细表都会保存在同一个数据库中,如果我们仅仅是对主订单信息进行查询获取包含了子订单信息的订单列表时,就会出现跨库join的问题,其对分布数据层带来的不良影响其实跟之前所说的全表扫描是一样 的。所以还是建议采用仅仅做异构索引表,而不是数据全复制。
实现对数据的异构索引创建有多种实现方式,
- 一种是数据库层采用数据复制的方式实现;
- 另一种是如图所示,在应用层实现,在这一层实现异构索引数据的创建,就必然会带来分布式事务的问题。另一种是如图所示,在应用层实现,在这一层实现异构索引数据的创建,就必然会带来分布式事务的问题。
这里给大家介绍的是目前阿里内部使用的方式,命名为精卫(精卫填海)。精卫是一个基于Mysql的实时数据复制框架,也可以认为是一个Mysql的数据触发器+分发管道。
精卫通过抽取器(Extractor)获取到订单数据创建在Mysql数据库中产生的binlog日志,并转换为event对象,然后通过过滤器Filter(比如字段过滤、转换等)或基于接口自定义开发的过滤对event对象中的数据进行处理,最终对分发器Applier将结果转换为发给DRDS的sql语句。通过精卫实现异构索引数据的过程如图
多线程管道实现
在精卫早期,数据的同步均采用单线程管道任务模式。但是随着业务的发展,需要同步的数据量越来越大,单纯的单线程管道任务已成为系统瓶颈,后来开发了对多线程的支持,如图
但多线程管道就会带来数据同步的问题。在对binlog数据进行多线程并行处理后,就不能保证在源数据库中执行的SQL语句在目标数据库的顺序一致,这样在某些场景中一定会出现数据不一致性的问题。对于这个问题,目前精卫中提供的解决思路是保证同一条记录或针对同一分库分表发生的数据同步按照顺序执行。
如果最后发送到分布式数据层的SQL语句中没有分库分表键,则通过对“库名+表名+主键值”哈希后对线程数取模,这样就能让同一条记录的数据同步事件处理都会在同一线程中顺序执行,保证了该记录多次变更的顺序性,但是不能保证不同记录间的顺序。如果sql语句中有分库键,则通过“库名+分库键值”哈希后对线程取模,效果是保证不同逻辑表针对相同分库逻辑的记录变化顺序。
精卫相关知识可参看:
https://yq.aliyun.com/articles/2892
https://blog.csdn.net/rainforc/article/details/84768890
https://www.cnblogs.com/dongqingswt/archive/2013/05/23/3095974.html -
索引表查找-c语言
2018-06-12 16:53:07* 创建索引表的基本思路是: * 将一个线性表(主表)根据一定的函数关系或条件划分为若干子表 * 然后为每个字表创建一个索引项 * 将这些索引项组合在一起构成一个可以索引主表的索引表 * * 索引表中每个索引.../******************************************** * 创建索引表的基本思路是: * 将一个线性表(主表)根据一定的函数关系或条件划分为若干子表 * 然后为每个字表创建一个索引项 * 将这些索引项组合在一起构成一个可以索引主表的索引表 * * 索引表中每个索引项一般包括3部分内容: * 索引值(更具索引值可以找到对应的子表) * 子表的开始位置(字表第一个位置保存的位置) * 子表长度(保存子表的数量,避免查找越界) * **********************************************/ #include<stdio.h> #include<stdlib.h> //索引表长度 #define INDEXTABLE_LEN 3 //主表长度(或者说大小) #define TABLE_LEN 30 //定义索引项 typedef item{ int index; int start; int length; }INDEXITEM; //定义索引表,索引表中可以包含100个记录 INDEXITEM indextable[INDEXTABLE_LEN]={ {10801,0,6}, {10802,10,4}, {10803,20,4} } //定义主表数据 long stu[TABLE_LEN]={ 1080101,1080102,1080103,1080104,1080105,1080106,0,0,0,0, 1080201,1080202,1080203,1080204,0,0,0,0,0,0, 1080301,1080302,1080303,1080304,0,0,0,0,0,0 }; /************************************************************* * 索引查找算法: * 先在索引表中查找关键字,再根据索引表中的索引项去主表中查找最终数据 * (1) 根据关键字key,按照定义的函数计算索引值index1, 在索引表中查找等于index1的索引项,确定对于字表在主表的开始位置和长度 * (2) 更具字表的开始位置,从此处开始顺序查找关键字key * *********************************************************/ int Index_Search(int key){ int i,index1,start,length; index1=key/100; for(i=0;i<INDEXTABLE_LEN;i++) //在索引表中查找索引值 { if(indextable[i].index==index1) //找到索引值 { start=indextable[i].start; //获取数组开始序号 length=indextable[i].length; //获取元素长度 break; //跳出循环 } } if(i>=INDEXTABLE_LEN) return -1;//索引表中查找失败 for(i=start;i<start+length;i++) { if(stu[i]==key) //找到关键字 return i; //返回序号 } return -1; //查找失败,返回-1 } /***************************************************** * 插入删除操作其实设计的操作很简单,只需要改变主表长度以及插入元素对应所在子表的长度 * ***************************************************/ int Insert(int key) { index1=key/100; for(i=0;i<INDEXTABLE_LEN;i++) //在索引表中查找索引值 { if(indextable[i].index==index1) //找到索引值 { start=indextable[i].start; //获取数组开始序号 length=indextable[i].length; //获取元素长度 break; //跳出循环 } } if(i>=INDEXTABLE_LEN) return -1;//索引表中查找失败 stu[start+length]=key;//保存关键字到主表 indextable[i].length++;//修改索引表中的子表长度 return 0; }
-
索引表和ES的一点点思考
2018-03-01 12:22:47索引表设计 在电商项目中,物理库存系统是个极其重要的系统,订单支付后,就会开始来占用物理库存。一般情况下,库存系统都是要分库的,因为主要的操作是写操作,例如占用/释放/取消等写操作。使用分库可以降低...索引表设计
在电商项目中,物理库存系统是个极其重要的系统,订单支付后,就会开始来占用物理库存。一般情况下,库存系统都是要分库的,因为主要的操作是写操作,例如占用/释放/取消等写操作。使用分库可以降低数据库写的压力。尽管写操作为主,但是读操作也是有的。比如说,库存占用的时候,得先查询是否有库存,而这个查询操作并不都会带上分库因子(用于路由到具体的某个数据库),而是一些比较宽松的查询条件,这些查询条件对应的数据可能分布在不同的数据库上。这个时候为了查询的方便,会构建一个索引表。这个索引表是存在另外的单独的一个数据库中,不会再分库了的。
比如说一个查询商品的操作,只是按照价格去搜索的时候,如下图:
这个时候就得从几个DB里面去获取数据,需要遍历DB,相当的麻烦。当然也可以为价格建立索引,加快查询速度,但是要知道,查询的时候,可能还根据其他条件来查询,像上下架状态,商品类别等,不可能都为这些查询条件建立索引,代价太大了,也不合理。引入索引表之后,则不同了。
根据查询条件从索引表中找出主键ID,再根据主键ID从多个数据库中查找数据。这样无论查询条件有哪些,通通只需要根据主键ID查找数据即可。当然索引表的设计不只是像上图那样设计,大概分三种。
1、查询字段+数据库主键
把查询字段放到索引表,还需要把对应的数据库主键ID也放置进去。当查询请求到来时,根据查询条件找出对应的数据主键,再根据数据主键路由到对应的存有完整业务数据的数据分库上。这种方案呢。索引表占用空间小,可以支撑很久。但是要找出业务数据,还是需要路由到分库上。另外,如果要把索引表的数据存储到ES搜索引擎上的话,这种方式就不行了。因为索引表中没有外部系统要的业务数据。所以当时的库存系统没有使用这种索引表设计方案。
2、查询字段+数据库主键+需要展示的业务字段
这种方案呢。当请求到来的时候,直接查询索引表即可。无需根据主键路由到分库了。同时如果要结合ES的话。可以直接把索引表的数据弄到ES上即可。后续直接让ES暴露查询接口即可。目前我在唯品会参与的物理库存项目中,是使用这种方式的。但是这个方案也有个缺点。就是索引表的体积比较大,后续数据量一大的话,也是个问题。能不能优化一下呢?
3、索引表拆分
上面说到的第二种方案,索引表的膨胀可能很快,可以考虑将索引表拆分。比如说:索引表只是保存查询条件和主键,而需要展示给外部系统的数据,另外存储在单独的表上。比如叫index_detail表。这个表拥有索引表的主键。这样的话,当查询请求到来的时候,先从索引表查询到主键,再根据主键从index_detail表中查询出数据。当然这样做的话。ES的数据来源就变成多张表了,不过这是可以接受的。
如何把业务数据写入到索引表
使用MQ
一般来说,构建索引数据是使用单独一个应用来做的。比如叫data-index域。这个域会从消息队列中读取消息,用于构建索引数据。当业务数据发生变化后,生产者发送MQ消息到队列上。
这里的消息设计也分两种情况。一种是消息只是带有数据主键和操作类型(ADD/Update/DELETE),消费者拿到主键后再去DB获取完整的数据并插入到索引表中。另一种方案呢,是消息包含了大部分需要的字段,消费者拿到消息后直接把数据插入到索引表中。这两种消息设计,我在实际项目中都有用过。
直接操作DB
这种方案呢就比较粗暴,直接配置一个索引表库的数据源,当业务数据发生变化时,使用Mybatis或者JDBC把数据更新到索引表中。一般不建议这么做,一来构建索引数据的逻辑跟数据的CRUD操作融合在一起了。二来,操作其他数据库的数据,要么通过接口的方式,要么由单独的域来做。建议还是使用MQ的方式来构建索引数据。
如何把索引表数据弄到ES上
监听数据库表的数据变化
像在唯品会这边,自研了一个叫VDP的组件,使用storm job去监听索引表数据的变化,一旦有变化,就把数据同步到队列中,ES直接从队列中获取数据,并存储到ES上。
这种方案的好处是,我们无需写任何代码,数据自动可以同步到ES上。
使用MQ
如果公司内部没有开发VDP这样的组件,可以通过发送MQ消息的方式来将索引表的数据同步数据到ES上。
让ES暴露CUD接口
另外一种方案是,让ES暴露CUD接口,用于同步索引表数据。但是这样就跟ES耦合在一块了。不太推荐这么做。
当索引表结合ES后,交互流程就变成如下的形式了。
关于分页
在数据库分库的情况下,如果要分页展示数据的话,并且数据库数据的数量又特别庞大,可以借助ES,从ES获取分页数据。如果没有ES,只有索引表的话,那就直接在索引表中获取分页数据对应的ID,再从数据库中获取。
进一步的思考
1、ES不支持Group By后
再分页
这样的操作,所以在构建索引表的时候,可以事先计算好Group By的一些统计数据,并存储到索引表中;
2、一些后台应用中,如果数据库表的数量已经很大,好几个亿了,并且查询的SQL还非常变态,用数据库已经无法支持了,那么可以使用ES,查询速度快,也支持一些统计操作;
3、使用ES输出数据时,也有个坑。经常会拿到脏数据的。例如当数据发送变化后,构建索引数据并把索引数据同步到ES上是需要时间的,但是我们后台通常有将数据下架的操作,下架的操作操作完后,再次点击查询按钮,可能还是看到脏数据,因为数据同步到ES上没那么快。现在我还没想到很好的办法来解决这个问题。欢迎网友提些建议。 -
HBase 索引表结构
2017-12-26 14:08:201. 索引表的结构在HBase中,表格的Rowkey按照字典排序,Region按照RowKey设置split point进行shard,通过这种方式实现的全局、分布式索引,成为了其成功的最大的砝码每一个索引建立一个表,然后依靠表的row key来... -
AutoCAD颜色索引表与RGB颜色的对照表
2020-05-23 18:32:33CAD颜色索引表:RGB颜色的转换 1 255 0 0 2 255 255 0 3 0 255 0 4 0 255 255 5 0 0 255 6 255 0 255 7 255 255 255 8 128 128 128 9 192 192 192 10 255 0 0 11 255 127 127 12 204 0 0 13 204 102 102 14 153 0 0 ... -
解决Hbase数据更新Phoenix对应索引表不更新问题
2018-03-15 23:21:06用户访问的数据接口直接走Phoenix,Phoenix的表是映射hbase产生,Phoenix的表会建很多索引,这时候问题就出现了,正常通过接口直接写数据进Phoenix表,相应的索引表也是会更新的,但是直接写数据到底层hbase表,这... -
索引表简介
2012-04-12 23:52:45索引表简介 1、索引的内部构造 因为在索引表中涉及到索引的内部构造知识,所以下面会进行简单的介绍。 首先,如果没有索引,当你想要去查找某个值的时候,你不得不对数据进行顺序扫描,如果一张表有n行,那么使用... -
重新理解SQL Server的聚集索引表与堆表
2016-01-22 10:07:40简述SQL Server表的类型由于当前关系型数据库...如下将描述MS SQL Server的聚集索引表与堆表,以便大家重新理解。SQL Server只存在2种表: 聚集索引表(Clustered table) 堆表(Heap) 简单的说,含有聚集索引 -
索引表
2010-05-06 15:03:00在我们传统的印象中,索引和表是两个不同的东西。我们总是先创建表,然后根据查询,建立相应的索引。表和索引在物理上属于不同的存储空间。 例如你建立了一个好友的通讯录,你经常需要通过指定好友的姓名来查询他的... -
oracle查看索引表空间
2013-09-06 11:45:54摘要: Oracle 查看索引表空间,Oracle 查看索引表空间语句,包括查看表空间的使用情况、查看数据库库对象、查看数据库的版本、查看数据库创建日期和归档方式、查询数据库中索引占用表空间的大小。 Oracle 查看表... -
数据结构------建立一个词索引表
2013-10-17 21:51:12最近复习数据结构与算法,就把《数据结构(C语言版)》(清华大学,严蔚敏)拿出来看,在串的那一章的最后有一个程序设计题--------建立一个词索引表,写了一下,代码如下。、 文件1:define.h 内容:各种数据类型的... -
Oracle 创建索引表空间语法
2015-07-10 17:49:43Oracle 的索引可分为5种,它们包括唯一索引、组合索引、...CREATE INDEX 索引名 ON 表名 (列名)TABLESPACE 表空间名; 例如: 以下为引用内容: CREATE INDEX idx_of_imsi ON uim_auth_file(imsi) TABLESPACE use -
数据库表结构及索引设计
2021-12-13 20:31:52数据库表设计 良好的表结构设计是高性能的基石,应该根据系统将要执行的业务查询来设计,这往往需要权衡各种因素。糟糕的表结构设计,会浪费大量的开发时间,严重延误项目开发周期,让人痛苦万分,而且直接影响到... -
Oracle中如何把表和索引放在不同的表空间里
2021-05-03 07:31:26因为:1)提高性能:尽量把表和索引的表空间存储在不同在磁盘上,把两类不同IO性质的数据分开放,这样可以提高磁盘的IO总体性能;2)便于管理:试想一下,如果索引的数据文件损坏,只要创建索引即可,不会引起数据丢失... -
索引顺序表
2018-09-18 20:16:171. 索引顺序表 索引顺序表的查找 查找成功时的平均查找长度 2. m 叉静态搜索树 静态索引结构 当数据表中的记录个数 n 很大时, 由于内存容量的限制,不能全部存入内存。因此,在查找过程中需要反复与外存交换... -
索引顺序表(分块)查找分析
2020-06-03 21:38:58索引顺序表(分块)查找一、分块查找表存储结构1、"分块有序"的线性表2、索引表二、分块查找的基本思想三、分块查找示例四、算法分析——平均查找长度ASL 索引顺序查找又称分块查找(Blocking Search)。它是一种性能... -
MySQL查看表索引
2021-01-18 22:46:25· Table表的名称。· Non_unique如果索引不能包括重复词,则为0。如果可以,则为1。· Key_name索引的名称。· Seq_in_index索引中的列序列号,从1开始。· Column_name列名称。· Collation列以什么方式存储在索引... -
oracle查看索引所在表空间及索引重建
2019-07-02 08:31:00select index_name,tablespace_name from dba_indexes where index_name='INDEX_PS'; 移动 alter index INDEX_PS rebuild ...对索引INDF5进行分析 analyze index INDF5 validate structure; 从视图INDEX_STA... -
颜色索引表(颜色查找表)
2010-05-25 13:13:00对于一个256色(BPP=8)的800*600分辨率的图像而言,若R、G、B分别采用一个字节描述,则需要800*600*3...以下是一个256色的颜色索引表的例子——————————————————————————————index R -
phoenix索引
2018-12-16 01:55:52现实中,业务查询需求条件往往比较复杂,带有多个查询字段组合,如果用HBase查的话,只能全表扫描进行过滤,效率很低。而Phoenix支持除rowkey外的其它字段的索引创建,即二级索引,查询效率可大幅提升。 为什... -
hive表之索引
2018-11-21 10:51:091,查看表employees索引信息: show formatted index on employees 2,说明: 原表是user 创建索引后的表是user_index_table 索引是user_index 先创建原表 create table user( id int, name string ) ... -
-
oracle查询索引(oracle查看表索引)
2021-04-30 10:02:20oracle查询索引(oracle查看表索引)2020-07-24 11:01:26共10个回答选中表右键View然后查看index通过PL/SQL可以直接查看某表是否建索引,通过SQL查询selectstatus,T.*fromuser_indexesTwheretable_name='表名'oracle... -
SAP表索引
2018-11-22 10:43:43SAP表索引 当我们在SE11下创建并激活一张表后,该表会自动生成自己的主索引用于确定主键。 一般情况下主索引只会随着主键的改变而改变,除非遇到一些奇怪的BUG会让主索引失效 与主索引不同,二级索引可以... -
IOS第二十一天——索引表和分组表
2013-05-05 22:14:32表格有分组表和索引表两种,那么这两种表格各有优势,具体可以根据实际应用的需求来进行选择,我们可以根据如下所示来实现分组表和索引表: OK,知道如何得到分组表和索引表之后,我们来尝试下实现第三种风格的... -
Oracle数据库如何查看表中索引
2021-03-20 01:18:561、查看表中有哪些索引 select * from user_indexes where table_name = '表名' 或者 select * from all_indexes where table_name = '表名' 2、查看表中索引对应哪些列 select * from user_ind_columns where ... -
oracle索引组织表(Index Organizied Table)
2017-02-13 17:14:38索引组织表(index organized table, IOT)就是存储在一个索引结构中的表。存储在堆中的表是无组织的(也就是说,只要有可用的空间,数据可以放在任何地方),IOT中的数据则按主键存储和排序。对你的应用来说,IOT表和一... -
线性索引(稠密索引、稀疏索引即分块索引、多重表、倒排表)
2017-10-17 16:07:06所有索引项的集合构成该文件的索引表。保存在磁盘上的索引表又称索引文件。索引技术是组织大型数据库以及磁盘文件的一种重要技术。索引按照结构可以分为线性索引,树形索引和多级索引。所谓线性索引就是将索引项集合...