Cosmos DB:更快的搜索选项

问题描述

我们有一个巨大的 cosmosDB 容器,包含数十亿行和近 300 列。数据按照我们大多数时候查询的方式进行分区和建模。

例如:用户表由 userId 分区,这就是为什么下面的查询工作正常。

Select * from User where userId = "user01234"

但在某些情况下,我们需要以不同的方式查询需要排序然后查询的数据。

例如:使用用户帖子和发布日期从用户表中获取数据

Select * from user where userPostId = "P01234" orderBy date limit 100

这个查询需要很多时间,因为数据的大小和数据没有基于 query2(用户 Post)进行分区。

我的问题是 - 当数据未进行相应分区时,我们如何使 query2 和其他类似查询更快。

选项 1:“创建按 Query2 分区的单独集合”- 这将使查询更快,但对于任何新查询,我们最终都会创建一个新集合,这是数十亿条记录的重复。 [昂贵的选择]

选项 2:“在 DB 之上构建弹性搜索?”这是一个耗时的选项,对于这个缓慢的查询问题可能会造成过度杀伤。

还有其他可以使用的选项吗?让我知道你的想法。

提前致谢!

解决方法

这两种选择都很昂贵。关键是决定哪个更便宜,包括运行跨分区查询。这将需要您计算出每个选项的成本。

对于跨分区查询,捕获响应对象中的 RU 费用,以便您了解其成本。

对于更改源,当您在现有集合上运行它时,这将产生前期成本,但该成本是否仍然很高取决于每月插入或更新的数据量。计算填充第二个集合的成本需要一些工作。您可以首先在执行插入时测量响应对象中的 RU Charge,然后乘以行数。计算您需要多少吞吐量将取决于您希望填充第二个集合的速度。它也是您用于读取和写入数据到第二个集合的计算量和实例数的函数。

一旦填充了第二个集合,Change Feed 将花费 2 RU/s 来轮询更改(顺便说一句,这是可配置的)和 1 RU/s 来读取每个新项目。将数据插入到第二个集合中的成本与您之前测量时的成本无关。

如果第二个查询没有那么频繁地运行并且您的数据没有发生太多变化,那么更改提要可以为您节省资金。如果您经常运行此查询并且您的数据也经常更改,那么更改 Feed 仍然可以为您省钱。

关于弹性搜索或 Azure 搜索,我通常发现这比保留跨分区查询或更改提要更昂贵。特别是如果您只是为了回答第二个查询而这样做。通常,当您需要真正的自由文本查询功能时,这是一个更好的选择。

您可能探索的第三个选项是使用 Azure Synapse Link,然后使用 SQL Serverless 或 Spark 运行这两个查询。

其他一些观察。

除非您在运行的这些查询中需要所有 300 个属性,否则您可能需要考虑将这些项目分解为单独的文档并存储为单独的行。特别是如果您有高度不对称的更新模式,其中只有少数属性经常更新。这将为您节省大量的更新费用,因为您更新的项目越小,它就越便宜(也更快)。

我建议的另一件事是查看您的索引策略并排除查询的 where 子句中未使用的每个属性,并包括使用的属性。这将对插入的 RU 消耗产生巨大影响。另请查看日期属性的复合索引,因为这对使用 order by 的查询产生巨大影响。