当前位置: 首页 > news >正文

Azure设计模式之索引表

为经常被查询的数据存储区中字段创建索引。使得应用程序能够更快速地从数据存储区检索数据,从而可以提高查询性能。


问题背景
许多数据存储使用主键来数据集。应用程序可用于查找和检索数据。下图显示了保存客户信息的数据存储示例。主键是客户ID。该图显示了由主键(客户ID)进行组织的客户信息。



虽然主键对于获取其键值的数据非常有用,但如果应用程序需要使用其他字段进行数据查询时,可能无法使用主键。在"客户"示例中,如果应用程序仅通过引用某个其他属性值(如客户所在的城镇)来查询数据,就无法使用"客户ID"主键来检索。要执行这样的查询,应用程序可能必须扫描每个客户记录,这是一个缓慢的过程。


许多关系数据库系统支持二级索引。二级索引是由一个或多个非主键的字段组织的数据结构,它存储每个索引值对应数据的位置。二级索引通常会存储索引键对应的值,以便进行快速查找。这些索引通常由数据库系统自动维护。


可以根据需要创建多个二级索引,以便应用程序可执行不同查询。例如,在关系数据库的"客户"表中,客户ID是主键,如果应用程序经常使用城镇列来过滤客户,则可考虑将"城镇"字段上添加到二级索引。


但是,尽管二级索引在关系数据结构中很常见,而云应用程序所使用的大多数是NoSQL数据存储的,并没有提供等效的功能。


解决方案
如果数据存储不支持二级索引,则可以通过创建自己的索引表来手动进行管理。索引表可按指定的键来组织数据。通常有3种策略来构造索引表,具体取决于所需二级索引的数量和应用程序所执行查询的性质。


第一种策略是复制全部数据到每个索引表中,但用不同的键(完整的规范化)来组织。下图显示了按城镇和姓氏来组织相同客户信息的索引表。



如果相对于使用每个键查询的次数来说,数据是静态的,那么这样做是恰当的。如果数据是比较动态的,则维护每个索引表的开销太大。此外,如果数据量非常大,则存储重复数据所需的空间量也会很大。


第二种策略是创建由不同键组织的规范化索引表,并使用主键来引用原始数据,而并非复制,如下图所示。原始数据称为fact表。



这种技术节省了空间,也减少了维护重复数据的开销。缺点是应用程序必须执行两个查找操作才能使用二级索引键来查找数据。它必须在索引表中找到数据的主键,再使用主键来查找事实数据表中的信息。


第三种策略是创建由不同的键组成的部分规范化的索引表,这种做法是重复频繁检索的字段。引用事实数据表访问不太频繁访问的字段,下图显示了在每个索引表的常见复制方式。



使用这种策略,就可以在前两种方法之间取得权衡。通过使用单项查找以快速检索常用查询的数据,而空间和维护开销并不至于像复制整个数据集那样严重。


如果应用程序经常通过某些值的组合来查询数据(例如,"查找住在雷蒙德的所有客户,并且姓氏为Smith"),则可以将索引表中的项的键实现为城市属性和"姓氏"属性的组合。下图显示了基于复合键的索引表。这些键先按城镇排序,然后再按姓氏对具有相同值的记录进行分类。



索引表可以加快对切分环境下数据的查询,并且在对切分键进行哈希运算时特别有用。下图显示了一个示例,其中的切分键是客户ID的哈希值。索引表可以按非哈希值(城镇和姓氏)来组织数据,并将哈希切分键作为查找数据。如果需要检索属于某个范围内的数据,或者需要按非哈希键的顺序来查询数据,则可重复计算哈希键(一个昂贵的操作)来保存应用程序信息。例如,在索引表中找到匹配的项(它们都存储在一个连续的块中),可以快速完成诸如"查找在雷德蒙中生活的所有客户"之类的查询。然后,使用存储在索引表中的切分键来引用客户数据。



问题和注意事项
在决定如何实现此模式时, 考虑以下几点:
维护二级索引的开销可能很大。必须对应用程序所使用的查询进行分析。仅当查询频率很高,并需要索引表时才去创建。不要持有投机心理去创建索引表来支持并不执行的查询,或只是偶尔执行。


索引表中数据复制可增加存储成本以及维护数据多个副本所需的工作量。将索引表实现为引用原始数据的规范化结构,需要应用程序执行两个查找操作来完成查询。第一个操作会搜索索引表获取主键,第二次使用主键获取数据。


如果系统在非常大的数据集中合并了多个索引表,则很难保持索引表和原始数据之间的一致性。可能可以围绕最终一致性模型来设计应用程序。例如,若要插入、更新或删除数据,应用程序可将消息发送到队列,并由单独的任务来执行,并异步去维护引用此数据的索引表。有关实现最终一致性的详细信息, 请参阅数据一致性入门。(https://msdn.microsoft.com/library/dn589800.aspx)


微软Azure存储表支持对在同一分区(称为实体组事务)中保存的数据所发生的事务进行更新。如果可以在同一分区中存储事实数据表和一个或多个索引表,则可使用此功能来帮助确保一致性。


索引表本身可能被分区或切分。


何时使用此模式
当应用程序经常需要使用主(或切分)键以外的键来检索数据,使用此模式可以提高查询性能。


此模式在以下情况下可能不会有帮助:
数据不稳定。索引表可能很快就会过时导致失效,或者索引表的维护开销大于使用它所带来的性能提升。
选择作为索引表的二级索引字段是较难确定的,并且取值范围很小(例如,性别)。
选择作为索引表的二级索引字段的数据值的余额是高度失衡的。例如,如果90%的记录在一个字段中包含相同的值,那么创建和维护一个索引表来查找基于此字段的数据可能会产生比按顺序扫描数据更高的开销。而对于非常频繁的查询,如果将目标值放在剩余的10%中,则此索引可能很有用。因此应该了解应用程序正在执行的查询以及它们的执行频率。
例子
Azure存储表为在云环境运行的应用程序提供了高度可伸缩的键/值数据存储。应用程序通过指定键来存储和检索数据。数据可以包含多个字段,但数据项的结构对表存储是不透明的,只将数据项当作字节数组处理。


Azure存储表还支持切分。切分键包括两类元素:分区键和数据行键。具有相同分区键的项存储在同一个分区(切分),并且在每个切分中的数据按行键顺序存储。Azure的表存储针对在分区内连续的行键值范围内的数据查询进行了优化。如果要构建在Azure表中存储信息的云应用程序,可考虑使用此功能。


例如,考虑存储有关电影信息的应用程序。该应用程序经常通过题材(动作,纪录片,历史,喜剧,戏剧等)来查询电影。可以使用题材作为分区键,为每个题材创建一个带有分区的Azure表,并将影片名称指定为行键,如下图所示。



如果应用程序还需要通过主演来查询电影,这种方法就不那么有效了。在这种情况下,可创建一个单独的Azure表作为索引表。分区键是主角,行键是影片名称。每个参与者的数据存储在不同的分区中。如果一个电影中明显不止一个,相同的电影将存在多个分区。


通过采用上面的解决方案中描述的第一种方法,可以在每个分区的值中复制影片数据。但是,每部影片可能会被多次复制 (每个演员一次),因此,当部分规范化数据以支持最常见的查询(如其他参与者的名称),并使应用程序能够使用分区键来检索其余的信息。这种方法在"解决方案"中的第三个选项提到了。下图显示了这种方法的实现。



相关模式阅读
在实现此模式时, 以下模式也可能是相关的:


数据一致性入门(https://msdn.microsoft.com/library/dn589800.aspx?f=255&MSPPError=-2147217396)。索引表必须作为索引更改的数据进行维护。在云中,作为修改数据的同一事务的一部分,可能无法或不适合执行更新索引的操作。在这种情况下,最终一致的方法更合适。这篇文章提供有关最终一致性问题的信息。


切分模式(https://docs.microsoft.com/en-us/azure/architecture/patterns/sharding)。索引表模式经常与数据分区结合使用。切分模式提供了有关如何将数据存储区划分为一组切片。


实例化视图模式(https://docs.microsoft.com/en-us/azure/architecture/patterns/materialized-view)。与其对数据进行索引用以支持汇总数据的查询,不如创建数据的实例化视图。这里描述了如何使用数据生成填充视图来高效完成汇总查询。

相关文章:

  • 你该如何填报高考志愿?
  • 网管师与网管员和 网络工程师的区别
  • Azure设计模式之领导者选举
  • 如何从零开始开发一款嵌入式产品(20年的嵌入式经验)
  • Azure设计模式之实例化视图
  • Azure设计模式之管道过滤器模式
  • 用系统函数获取当前季度
  • Azure设计模式之优先消息队列
  • Azure应用部署方式对比
  • BadImageFormatException or An attempt was made to load a program with an incorrect format
  • 获取中国标准时间(由美国官方时间折算)
  • C# 使用ExcelReader 上传excel
  • Nebula3 Render Application Wizard
  • 使用red5+ffmpeg读取ip摄像头流并广播rtmp
  • WCF中使用MSMQ无法传送自定义对象
  • Babel配置的不完全指南
  • Brief introduction of how to 'Call, Apply and Bind'
  • iOS 颜色设置看我就够了
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • java概述
  • Next.js之基础概念(二)
  • python3 使用 asyncio 代替线程
  • React as a UI Runtime(五、列表)
  • Spring框架之我见(三)——IOC、AOP
  • TypeScript实现数据结构(一)栈,队列,链表
  • 闭包,sync使用细节
  • 初识 beanstalkd
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 如何优雅地使用 Sublime Text
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 使用 QuickBI 搭建酷炫可视化分析
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 项目管理碎碎念系列之一:干系人管理
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • nb
  • ​ArcGIS Pro 如何批量删除字段
  • # C++之functional库用法整理
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (Oracle)SQL优化技巧(一):分页查询
  • (办公)springboot配置aop处理请求.
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (一)Neo4j下载安装以及初次使用
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • ./configure,make,make install的作用
  • .form文件_一篇文章学会文件上传
  • .Mobi域名介绍
  • .NET Core跨平台微服务学习资源
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .NET下ASPX编程的几个小问题
  • .pyc文件是什么?
  • @Service注解让spring找到你的Service bean