我们即将在内部实施CQRS系统的Read部分,目标是大幅提高我们的读取性能。目前,我们的读取是通过Web服务进行的,该服务针对规范化数据运行Linq-to-SQL查询,涉及从SQL Azure数据库进行某种程度的反序列化。
我们数据的简化结构是:
我想将其转换为非规范化状态,以便当用户请求查看从EITHER读取的消息提要时:
Azure表存储中保存的非规范化表示
Azure表存储中保存的规范化表示
OR
SQL Azure中保存的非规范化表示
我要问的是,是否有人在Table Storage或SQL Azure中实现非规范化结构,您会选择哪种?还是有一种我错过的更好的方法?
我的直觉说表存储中的标准化(至少在某种程度上)数据是可行的方法;但是我担心它会降低性能,以便进行3次查询以获取用户的所有数据。
答案 0 :(得分:9)
考虑使用Azure表的主要驱动因素是大大提高读取性能,而在使用SQL Azure的场景中,使用的速度要慢得多。"根据您在SQL Azure中保存的非规范化表示的最后一点"。由于一些原因,我个人觉得这非常令人惊讶,并会要求详细分析这种说法是如何做出的。我的默认位置是在大多数情况下,SQL Azure会更快。
以下是我对该主张持怀疑态度的一些原因:
虽然您可以通过创建包含自定义索引的其他表来伪造Azure表中的索引,但您有责任维护该索引,这会降低您的操作速度,并且如果您不小心,可能会创建孤立方案。
最后但并非最不重要的一点是,当您尝试降低存储成本(比SQL Azure便宜)以及需要比SQL Azure提供的更多存储时,使用Azure表通常是有意义的(尽管您现在可以使用Federations打破单个数据库的最大存储限制)。例如,如果您需要存储10亿条客户记录,则使用Azure Table可能有意义。但是在我看来,单独使用Azure Table提高速度是相当可疑的。
如果我在你的帮助下,我会非常努力地质疑这一说法,并确保您拥有专业的SQL开发技能,可以证明您在完全更改架构之前已经达到了SQL Server / SQL Azure固有的性能瓶颈。
此外,我会定义您的表现目标。您是否希望访问时间快100倍?您是否考虑过缓存?您是否在数据库中正确使用索引?
我的2美分......:)
答案 1 :(得分:6)
我不会尝试争论 CQRS 的确切定义。当我们谈论 Azure 时,我将使用它的文档作为参考。从那里我们可以找到:
CQRS不需要,您需要使用单独的读取存储。
为进一步隔离,您可以将读取数据与写入数据物理隔离。
“您可以”并不意味着“您必须”。
关于非规范化和读取优化:
尽管
基于 CQRS 的系统的读取模型提供了数据的物化视图,通常是高度非规范化的视图
关键是
读取的数据库可以使用自己的数据针对查询进行了优化的模式
它可以是一个不同的模式,但是仍然可以被规范化,或者至少不能被“高度非规范化”。再次-您可以,但这并不意味着您必须。
此外,如果由于写锁而不是由于繁重的SQL请求而导致性能不佳:
读取存储区可以是写入存储区的只读副本
当我们谈论请求的优化时,最好多讨论请求本身,而少讨论存储类型。
关于“它从任一读取” [...]
“材料化视图” 模式描述了在源数据不适合查询的格式且难以生成合适的查询的环境中生成数据的预填充的视图 ,或者由于数据或数据存储的性质而导致查询性能不佳的地方。
关键是视图是复数。
实例化视图甚至可以仅针对单个查询进行优化。
...
材料化视图通常专门针对一个或少量查询量身定制
因此您不在这3个选项之间进行选择。实际上,它要宽得多。 同样,您不需要其他存储来创建视图。所有这些都可以在单个DB中完成。
关于
我的直觉说,表存储中的规范化数据(至少在某种程度上)将是解决之道;但是我担心进行3次查询以获取用户的所有数据会降低性能。
是的,性能当然会受到损害! (也要考虑一致性问题)。但是,这是否可以,您必须先进行测试才能确定。随着您的数据和您的请求。因为数据传输的延迟实际上可以少于一些精心设计的SQL请求所需的时间。
所以一切归结为:
这些您只能回答自己。这些选择与性能无关。因为这两个指标中都有如果有合适的指标,我认为效果几乎是无法区分的。
总结:
SQL Azure还是Azure表存储?
对于不同的请求和数据,您可能应该同时使用两者。但是问题中的信息太少,无法给您确切的答案(我们需要确切的要求)。但我同意@HerveRoggero-很可能您应该坚持使用 SQL Azure 。
答案 2 :(得分:2)
我不确定是否可以为其他答案添加任何值,但是我想引起您的注意,是根据您的查询路径对数据存储进行建模。您要一起查询所有提到的数据位吗?用户是否会在单击或进行其他操作后要求其中一些作为其他信息?我假设您已经考虑过这个问题,并且您肯定希望一次性查询所有内容。即,API或某些东西需要立即返回所有这些信息。
在这种情况下,没有什么比用键查询单个对象更好的了。如果您是专门谈论Azure's Table Storage,它会说这是一个键值存储。我很好奇您是否考虑过文档数据库(例如Cosmos DB)?如果要实现CQRS读取模型,则可以为每个用户生成一个文档,其中包含用户在Feed上看到的所有信息。您通过用户ID查询该文档,这将是关键。在我看来,这种方法将是最佳的CQRS实现,因为毕竟您的目标是实现 read 模型。除非我误解了您的问题,否则除非您有充分的理由不使用文档数据库。