c# - C# Azure CosmosDb 和 Mongo - 如何知道 Find 是否命中索引,以及针对这种情况的最佳索引建议是什么?
问题描述
我有一个 ASP.Net Core 3.1 API,它使用 Mongo Driver nuget package v2.11 将文档保存在 Azure CosmosDb 中。
首先,我的文档类:
public class Customer
{
public Guid CustomerId {get;set;}
public string Email {get;set;}
public int Channel {get;set;}
public string PartitionKey
{
get { return GetPartitionKey(CustomerId); }
set {; }
}
public static string GetPartitionKey(Guid id)
{
return id.ToString().Substring(0, 2);
}
}
在分享我的存储库类之前,我想分享一些关于我在这里遇到的情况的细节。我有一个分区集合(具有我的 Customer 类的 PartitionKey 属性),我对 Find 操作有两个要求:
- 能够通过 CustomerId 和 Channel 找到(不同的 Channel 可以存在相同的 CustomerId)
- 能够检查用户是否存在。如果同一渠道存在 CustomerId 或电子邮件,则客户存在(同样,不同渠道可以存在相同的 CustomerId 或电子邮件)
我的问题是关于适当的索引,以便在我通过分区键以外的其他东西找到它们时利用它们。让我们转到存储库类,然后转到索引:
public class MyRepository
{
private IMongoCollection<Customer> Collection;
public MyRepository()
{
MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl("The connection string"));
settings.SslSettings = new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };
var mongoClient = new MongoClient(settings);
var database = mongoClient.GetDatabase("db-customer");
this.Collection = database.GetCollection<Customer>("col-customer");
// What indexes here ?!?
}
public Customer GetByKey(Guid customerId, int channel)
{
var channelFilter = Builders<Customer>.Filter.Eq(x => x.Channel, customer.Channel);
var idFilter = Builders<Customer>.Filter.Eq(x => x.CustomerId, customer.CustomerId);
var filter = channelFilter & idFilter;
Customer result = this.Collection.Find(filter).FirstOrDefault();
return result;
}
public bool Exists(Customer customer)
{
var channelFilter = Builders<Customer>.Filter.Eq(x => x.Channel, customer.Channel);
var emailFilter = Builders<Customer>.Filter.Eq(x => x.Email, customer.Email);
var idFilter = Builders<Customer>.Filter.Eq(x => x.CustomerId, customer.CustomerId);
var filter = channelFilter & (emailFilter | idFilter);
bool found = this.Collection.Find(filter).FirstOrDefault() != null;
return found;
}
}
所以,我的问题是,这个存储库的最佳索引设置是什么?我是否应该为我正在搜索的每个字段创建一个索引,如下所示:
this.Collection.Indexes.CreateOne(new CreateIndexModel<Customer>(Builders<Customer>.IndexKeys.Ascending(i => i.CustomerId)));
this.Collection.Indexes.CreateOne(new CreateIndexModel<Customer>(Builders<Customer>.IndexKeys.Ascending(i => i.Channel)));
this.Collection.Indexes.CreateOne(new CreateIndexModel<Customer>(Builders<Customer>.IndexKeys.Ascending(i => i.Email)));
或者我应该创建复合索引,这取决于我尝试尝试的搜索,像这样?
this.Collection.Indexes.CreateOne(new CreateIndexModel<Customer>(Builders<Customer>.IndexKeys.Ascending(i => i.CustomerId).Ascending(i => i.Channel)));
this.Collection.Indexes.CreateOne(new CreateIndexModel<Customer>(Builders<Customer>.IndexKeys.Ascending(i => i.CustomerId).Ascending(i => i.Email).Ascending(i => i.Channel)));
通过使用 Azure 监视器检查指标,我总是获得较低的 RU 消耗和整体较短的响应时间,但我的存储库在此阶段有一些记录。恐怕随着记录数量的增加(这将有数百万条记录),RU 消耗变得太大或响应时间太长,或者在最坏的情况下,两者兼而有之。
我可以在这个问题上得到你的两分钱吗?谢谢。
解决方案
只有当您的查询需要同时对多个字段进行有效排序时,您才应该创建复合索引。对于具有多个不需要排序的过滤器的查询,创建多个单字段索引而不是单个复合索引。一个查询使用多个可用的单字段索引。
因此,就您而言,我看到您有多个不需要排序的过滤器。因此创建多个单字段索引。
推荐阅读
- c# - 如何检索存储在 Object 类中的列表
- json - ESP8266 在从 OpenWeatherMap 获取数据时正常运行一段时间后重置
- react-native - 一个屏幕上的多个堆栈导航器
- php - 如何以表格格式设置我的 php 电子邮件回复样式?
- python - ModuleNotFoundError:没有名为“瓶子”的模块
- angular - Angular ReactiveForm 显示值 OnPush
- android - Android:构建时指向 DI:dagger 的“构建失败”错误
- java - Html 输入数字仅接受自然数或带有 ,25 或 ,5
- angular - 我应该如何使用 transloco i18n(internationalization) 库更改 Material Table 标题以进行分页和页面范围、下一个、上一个按钮?
- r - 从 VBA 运行 R 脚本