0

使用 .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 是否有益于性能或成本?

4

2 回答 2

2

如果禁用自动生成,以下是生成新 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 地址
  • 时间戳
  • 额外的“紧急唯一性位”
  • 算法的标识符

请记住,仅当 Azure CosmosDB 服务使用与模拟器相同的 JS 代码时才适用(我个人认为它会这样做,但不能保证)。

总之,自动 id 生成更多的是一种生活质量功能,它为开发人员提供了更多控制权,而不是可以改善或恶化应用程序性能(或吞吐量)的东西。它归结为以下几点。如果将 Id 作为 DTO 的一部分是合乎逻辑的,那么就使用它。如果没有,则将其删除。但是请记住,ReplaceandUpsert操作需要id才能工作。

编辑:另外,再次阅读您的问题,如果开发人员id手动设置并且未禁用自动生成,那么 CosmosDB 将在指定的 id 之上自动生成一个新的 id。这不是真的。如果您id手动设置,则无论设置如何,CosmosDB 都不会覆盖 id。

于 2018-08-29T13:06:13.553 回答
0

我认为它不应该对性能产生太大影响(只有几毫秒),但是您可以获得使用 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;
    }
于 2018-08-29T21:15:37.497 回答