我们在生产环境中使用CosmosDB来存储HTTP请求/响应审核数据。该数据的结构通常如下:
{
"id": "5ff4c51d3a7a47c0b5697520ae024769",
"Timestamp": "2019-06-27T10:08:03.2123924+00:00",
"Source": "Microservice",
"Origin": "Client",
"User": "SOME-USER",
"Uri": "GET /some/url",
"NormalizedUri": "GET /SOME/URL",
"UserAgent": "okhttp/3.10.0",
"Client": "0.XX.0-ssffgg;8.1.0;samsung;SM-G390F",
"ClientAppVersion": "XX-ssffgg",
"ClientAndroidVersion": "8.1.0",
"ClientManufacturer": "samsung",
"ClientModel": "SM-G390F",
"ResponseCode": "OK",
"TrackingId": "739f22d01987470591556468213651e9",
"Response": "[ REDACTED ], <— Usually quite long (thousands of chars)
"PartitionKey": 45,
"InstanceVersion": 1,
"_rid": "TIFzALOuulIEAAAAAACACA==",
"_self": "dbs/TIFzAA==/colls/TIFzALOuulI=/docs/TIFzALOuulIEAAAAAACACA==/",
"_etag": "\"0d00c779-0000-0d00-0000-5d1495830000\"",
"_attachments": "attachments/",
"_ts": 1561630083
}
我们目前正在写大约150,000-200,000份类似于上述一天的文档,其中/PartitionKey
是在容器上配置的分区键路径。 PartitionKey的值是C#.net中在0到999之间随机生成的数字。
但是,我们看到每天的热点中,单个物理分区的最高速度可以达到2.5K-4.5K RU / s,而其他物理分区却非常低(大约200 RU / s)。由于需要为最大利用分区分配吞吐量,因此这对成本产生了影响。
第二个因素是我们存储了相当多的数据,接近1TB的文档,并且每天增加几GB。结果,我们目前大约有40个物理分区。
结合这两个因素,我们最终不得不至少提供120,000-184,000 RU / s之间的资源。
我应该提到,我们几乎不需要查询此数据;除了偶尔在Cosmos数据浏览器中进行临时手动构建的查询之外。
我的问题是...通过简单地使用“ id”列作为我们的分区键(或随机生成的GUID),在所需的RU / s和数据分配方面会好很多吗-然后设置合理的TTL,所以我们没有持续增长的数据集?
我知道这将要求我们重新创建集合。
非常感谢。
答案 0 :(得分:0)
尽管使用id或GUID可以提供比今天拥有的随机数更好的基数,但是您运行的任何查询都将非常昂贵,因为它始终是跨分区的,并且涉及大量数据。
我认为一个更好的选择是使用一个综合键,该键结合了多个具有高基数并且还用于查询数据的属性。可以在这里https://docs.microsoft.com/en-us/azure/cosmos-db/synthetic-partition-keys
了解更多信息就TTL而言,我绝对会为该数据所需的保留时间进行设置。 Cosmos会以未使用的吞吐量关闭TTL数据,因此永远不会成为问题。
最后,您还应该考虑(如果尚未使用)自定义索引策略,并排除任何从未查询过的路径。特别是“响应”属性,因为您说它的长度为数千个字符。在像您这样的写繁重场景中,这可以节省大量RU / s。
答案 1 :(得分:0)
根据我的经验,我发现宇宙倾向于随着新数据而降低。更多数据意味着更多身体参与。因此,您需要分配更多的吞吐量才能分配给它们中的每一个。当前,我们开始将旧数据归档到Blob存储中,以避免此类问题并保持物理分区数不变。我们使用波斯菊作为热存储,然后将旧数据作为blob存储作为冷存储。我们减少了分配给每个物理分区的RU,从而节省了资金。