在 CosmosDB 中创建文档时禁用 AutomaticIdGeneration 是否有性能优势?
Is there a performance benefit to disableAutomaticIdGeneration when creating documents in CosmosDB?
使用 .Net Core SDK 在 CosmosDB 中创建文档时,有一个选项可以禁用自动生成文档 ID。这将允许开发人员为 id
属性 设置自己的值,如果未设置,将抛出异常。
例如,此处显示了两种方法:
public class CosmosExample
{
private readonly IDocumentClient _docClient;
private Uri _collectionUri;
public CosmosExample(IDocumentClient docClient)
{
_docClient = docClient;
_collectionUri = UriFactory.CreateDocumentCollectionUri("MyDatabase", "MyCollection");
}
public async Task CreateWithId(DataModelWithId model)
{
model.id = Guid.NewGuid();
var result = await _docClient.CreateDocumentAsync(_collectionUri, model, disableAutomaticIdGeneration: true);
}
public async Task CreateAutoId(DataModel model)
{
var result = await _docClient.CreateDocumentAsync(_collectionUri, model);
}
}
public class DataModelWithId
{
public Guid id { get; set; }
public string Name { get; set; }
}
public class DataModel
{
public string Name { get; set; }
}
我正在编写一个创建大量文档的应用程序,我想优化吞吐量和 RU(请求单位)成本。
禁用自动 ID 生成并改为在代码中生成 ID 是否有利于性能或成本?
如果禁用自动生成,这里是生成新 GUID 的代码。
此代码是通过对 CosmosDB 模拟器进行逆向工程并提取 Javascript 引擎代码获得的。
// generate GUID
function getHexaDigit() {
return Math.floor(Math.random() * 16).toString(16);
}
function generateGuidId() {
var id = "";
for (var i = 0; i < 8; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 4; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 4; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 4; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 12; i++) {
id += getHexaDigit();
}
return id;
}
据此判断,服务器端生成速度更快,因为它没有考虑 C# Guid.NewGuid()
考虑的内容,而只是进行 RNG。
Guid.NewGuid()
实际上会考虑更多的东西来生成这个值。
- 用于生成 GUID 的机器的 MAC 地址
- 时间戳
- 额外"emergency uniquifier bits"
- 算法的标识符
请记住,只有当 Azure CosmosDB 服务使用与模拟器相同的 JS 代码时(我个人认为是这样,但不能保证),这才是正确的。
总而言之,自动生成 ID 更像是一种生活质量功能,它为开发人员提供了更多控制权,而不是可以提高或降低应用程序性能(或吞吐量)的功能。归结为以下几点。如果将 Id 作为 DTO 的一部分在逻辑上是有意义的,那么就使用它。如果没有,则将其删除。但是请记住,Replace
和 Upsert
操作需要 id
才能工作。
编辑:另外,再次阅读您的问题,听起来好像如果开发人员手动设置 id
并且未禁用自动生成,CosmosDB 将自动生成一个新的 id指定的那个。这不是真的。如果您手动设置 id
,则无论设置如何,CosmosDB 都不会覆盖该 ID。
我认为它应该不会对性能产生太大影响(只有几毫秒),但是您可以获得使用 GUID 和不使用 GUID 时不同的准确时间。在下面的代码中,我曾经通过查询获取消耗的 RU 和时间。
private static void Main(string[] args)
{
string docId = Guid.NewGuid().ToString();
string attId = Guid.NewGuid().ToString();
var myDoc = new { id = docId, Name = "Max", City = "Aberdeen" }; // this is the document you are trying to save
var client = GetClientAsync().GetAwaiter().GetResult();
var createUrl = UriFactory.CreateDocumentCollectionUri("mytestdb", "test");
ResourceResponse<Document> document = client.CreateDocumentAsync(createUrl, myDoc).GetAwaiter().GetResult();
// Measure the performance (request units) of writes
// ResourceResponse<Document> response = await client.CreateDocumentAsync(collectionSelfLink, myDocument);
Console.WriteLine("Insert of document consumed {0} request units", document.RequestCharge);
// Measure the performance (request units) of queries
IDocumentQuery<dynamic> queryable = client.CreateDocumentQuery(
UriFactory.CreateDocumentCollectionUri("mytestdb", "test"), "select top 1 * from c").AsDocumentQuery();
FeedResponse<dynamic> queryResponse = queryable.ExecuteNextAsync<dynamic>().GetAwaiter().GetResult();
Console.WriteLine("Query batch consumed {0} request units", queryResponse.RequestCharge);
Console.Read();
}
private static DocumentClient documentClient;
private static async Task<DocumentClient> GetClientAsync()
{
if (documentClient == null)
{
var endpointUrl = "https://catecosmos.documents.azure.com:443/";
var primaryKey = "73dDwfcDetx7Xr91kGs22QOkcgJgfMgyyJ8xKBbes6mooRtXY1vRo0gk5T5poFNAYviI9So53xsKgPiTsQ==";
documentClient = new DocumentClient(new Uri(endpointUrl), primaryKey);
await documentClient.OpenAsync();
}
return documentClient;
}
使用 .Net Core SDK 在 CosmosDB 中创建文档时,有一个选项可以禁用自动生成文档 ID。这将允许开发人员为 id
属性 设置自己的值,如果未设置,将抛出异常。
例如,此处显示了两种方法:
public class CosmosExample
{
private readonly IDocumentClient _docClient;
private Uri _collectionUri;
public CosmosExample(IDocumentClient docClient)
{
_docClient = docClient;
_collectionUri = UriFactory.CreateDocumentCollectionUri("MyDatabase", "MyCollection");
}
public async Task CreateWithId(DataModelWithId model)
{
model.id = Guid.NewGuid();
var result = await _docClient.CreateDocumentAsync(_collectionUri, model, disableAutomaticIdGeneration: true);
}
public async Task CreateAutoId(DataModel model)
{
var result = await _docClient.CreateDocumentAsync(_collectionUri, model);
}
}
public class DataModelWithId
{
public Guid id { get; set; }
public string Name { get; set; }
}
public class DataModel
{
public string Name { get; set; }
}
我正在编写一个创建大量文档的应用程序,我想优化吞吐量和 RU(请求单位)成本。
禁用自动 ID 生成并改为在代码中生成 ID 是否有利于性能或成本?
如果禁用自动生成,这里是生成新 GUID 的代码。 此代码是通过对 CosmosDB 模拟器进行逆向工程并提取 Javascript 引擎代码获得的。
// generate GUID
function getHexaDigit() {
return Math.floor(Math.random() * 16).toString(16);
}
function generateGuidId() {
var id = "";
for (var i = 0; i < 8; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 4; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 4; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 4; i++) {
id += getHexaDigit();
}
id += "-";
for (var i = 0; i < 12; i++) {
id += getHexaDigit();
}
return id;
}
据此判断,服务器端生成速度更快,因为它没有考虑 C# Guid.NewGuid()
考虑的内容,而只是进行 RNG。
Guid.NewGuid()
实际上会考虑更多的东西来生成这个值。
- 用于生成 GUID 的机器的 MAC 地址
- 时间戳
- 额外"emergency uniquifier bits"
- 算法的标识符
请记住,只有当 Azure CosmosDB 服务使用与模拟器相同的 JS 代码时(我个人认为是这样,但不能保证),这才是正确的。
总而言之,自动生成 ID 更像是一种生活质量功能,它为开发人员提供了更多控制权,而不是可以提高或降低应用程序性能(或吞吐量)的功能。归结为以下几点。如果将 Id 作为 DTO 的一部分在逻辑上是有意义的,那么就使用它。如果没有,则将其删除。但是请记住,Replace
和 Upsert
操作需要 id
才能工作。
编辑:另外,再次阅读您的问题,听起来好像如果开发人员手动设置 id
并且未禁用自动生成,CosmosDB 将自动生成一个新的 id指定的那个。这不是真的。如果您手动设置 id
,则无论设置如何,CosmosDB 都不会覆盖该 ID。
我认为它应该不会对性能产生太大影响(只有几毫秒),但是您可以获得使用 GUID 和不使用 GUID 时不同的准确时间。在下面的代码中,我曾经通过查询获取消耗的 RU 和时间。
private static void Main(string[] args)
{
string docId = Guid.NewGuid().ToString();
string attId = Guid.NewGuid().ToString();
var myDoc = new { id = docId, Name = "Max", City = "Aberdeen" }; // this is the document you are trying to save
var client = GetClientAsync().GetAwaiter().GetResult();
var createUrl = UriFactory.CreateDocumentCollectionUri("mytestdb", "test");
ResourceResponse<Document> document = client.CreateDocumentAsync(createUrl, myDoc).GetAwaiter().GetResult();
// Measure the performance (request units) of writes
// ResourceResponse<Document> response = await client.CreateDocumentAsync(collectionSelfLink, myDocument);
Console.WriteLine("Insert of document consumed {0} request units", document.RequestCharge);
// Measure the performance (request units) of queries
IDocumentQuery<dynamic> queryable = client.CreateDocumentQuery(
UriFactory.CreateDocumentCollectionUri("mytestdb", "test"), "select top 1 * from c").AsDocumentQuery();
FeedResponse<dynamic> queryResponse = queryable.ExecuteNextAsync<dynamic>().GetAwaiter().GetResult();
Console.WriteLine("Query batch consumed {0} request units", queryResponse.RequestCharge);
Console.Read();
}
private static DocumentClient documentClient;
private static async Task<DocumentClient> GetClientAsync()
{
if (documentClient == null)
{
var endpointUrl = "https://catecosmos.documents.azure.com:443/";
var primaryKey = "73dDwfcDetx7Xr91kGs22QOkcgJgfMgyyJ8xKBbes6mooRtXY1vRo0gk5T5poFNAYviI9So53xsKgPiTsQ==";
documentClient = new DocumentClient(new Uri(endpointUrl), primaryKey);
await documentClient.OpenAsync();
}
return documentClient;
}