gpt4 book ai didi

c# - MongoDB C# 驱动程序 : API vs Linq Performance

转载 作者:行者123 更新时间:2023-12-02 02:32:59 27 4
gpt4 key购买 nike

我正在尝试使用 IRepository 模式(C#、MVC5)制作 MongoDB Web 应用程序,以使其更容易进行单元测试。只是想知道是否有人可以向我提供有关为什么这更快的信息。

这使用了最新的 MongoDB C# 驱动程序。

在我的 IRepository 类中,我有以下内容

IQueryable<T> SearchFor();

List<T> SearchFor(FilterDefinition<T> filter);

发现一个 SO 帖子,建议使用 IQueryable 来提高使用 IEnumerable 的速度。

这是 MongoRepository 类的代码。

public IQueryable<T> SearchFor() {
return _collection.AsQueryable<T>();
}

public List<T> SearchFor(FilterDefinition<T> filter) {
return _collection.Find(filter).ToList();
}

据我所知,过滤器定义是您通常如何编写对数据库的查询的代码。

以下是从数据库获取数据的调用

IQueryable<Client> asd4 = collection.SearchFor().Where(x => x.ClientDesc == "<search text>");

FilterDefinition<Client> filter1 = Builders<Client>.Filter.Eq("ClientDesc", "<search text>");
List<Client> asd10 = collection.SearchFor(filter1).ToList<Client>();

请注意,我知道我可能应该使用 IQueryable 和 Linq 路由,只是因为 IRepository 不应该包含技术相关类(如 FilterDefinition)。

当针对包含 30k 简单文档的集合进行测试并测试不同方法的速度时,我得到以下结果。

使用 IQueryable 在 3 毫秒内完成,而使用 FilterDefinition 在 43 毫秒内完成。

我想知道为什么 IQueryable 上的 Linq 查询比使用 API 发送请求只是为了返回特定值更快?

<小时/>

更新:根据@lenkan的建议,我为 IQueryable 添加了一个 for every 循环。

public void PerformanceTest(IRepository<Client> collection) {
Stopwatch sw = new Stopwatch();

// Delete all records
// ******************
System.Diagnostics.Debug.WriteLine("*****************");

sw.Start();
collection.DeleteAll();
sw.Stop();
System.Diagnostics.Debug.WriteLine("Deleting all records: " + sw.Elapsed);


// Create 30k Records
// ******************
System.Diagnostics.Debug.WriteLine("*****************");

sw.Reset();
sw.Start();
// Create 30k records
for (int i = 0; i < 30000; i++) {
Client testclient = new Client() {
ClientDesc = "hahahahahahahahah " + i
};
collection.Add(testclient);
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Created: 30k rows: " + sw.Elapsed);


// Test IQueryable & LINQ
// **********************
System.Diagnostics.Debug.WriteLine("*********************");
System.Diagnostics.Debug.WriteLine("* IQueryable & LINQ *");
System.Diagnostics.Debug.WriteLine("*********************");

sw.Reset();
sw.Start();
IQueryable<Client> asd4 = collection.SearchFor().Where(x => x.ClientDesc == "hahahahahahahahah 10");
foreach (Client item in asd4) {
string aaaaaa = item.ClientDesc;
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find one from start: " + sw.Elapsed);

sw.Reset();
sw.Start();
IQueryable<Client> asd7 = collection.SearchFor().Where(x => x.ClientDesc == "hahahahahahahahah 10");
foreach (Client item in asd7) {
string aaaaaa = item.ClientDesc;
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find one from start: " + sw.Elapsed);

sw.Reset();
sw.Start();
IQueryable<Client> asd5 = collection.SearchFor().Where(x => x.ClientDesc == "hahahahahahahahah 29999");
foreach (Client item in asd5) {
string bbbbbb = item.ClientDesc;
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find one from end: " + sw.Elapsed);

sw.Reset();
sw.Start();
for (int i = 10000; i < 10050; i++) {
IQueryable<Client> asd6 = collection.SearchFor().Where(x => x.ClientDesc == "hahahahahahahahah " + i);
foreach (Client item in asd6) {
string aaaaaa = item.ClientDesc;
}
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find in loop of 50: " + sw.Elapsed);


// Test Filter & LINQ
// ***********************
System.Diagnostics.Debug.WriteLine("*****************");
System.Diagnostics.Debug.WriteLine("* List & Filter *");
System.Diagnostics.Debug.WriteLine("*****************");

sw.Reset();
sw.Start();
FilterDefinition<Client> filter1 = Builders<Client>.Filter.Eq("ClientDesc", "hahahahahahahahah 10");
List<Client> asd10 = collection.SearchFor(filter1).ToList<Client>();
foreach (Client item in asd10) {
string aaaaaa = item.ClientDesc;
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find one from start: " + sw.Elapsed);

sw.Reset();
sw.Start();
FilterDefinition<Client> filter2 = Builders<Client>.Filter.Eq("ClientDesc", "hahahahahahahahah 29999");
List<Client> asd11 = collection.SearchFor(filter2).ToList<Client>();
foreach (Client item in asd11) {
string cccccc = item.ClientDesc;
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find one from end: " + sw.Elapsed);

sw.Reset();
sw.Start();
for (int i = 10000; i < 10050; i++) {
FilterDefinition<Client> filter3 = Builders<Client>.Filter.Eq("ClientDesc", "hahahahahahahahah " + i);
List<Client> asd12 = collection.SearchFor(filter3).ToList<Client>();
}
sw.Stop();
System.Diagnostics.Debug.WriteLine("Find in loop of 50: " + sw.Elapsed);

// Delete all records
// ******************
System.Diagnostics.Debug.WriteLine("*****************");

sw.Start();
collection.DeleteAll();
sw.Stop();
System.Diagnostics.Debug.WriteLine("Deleting all records: " + sw.Elapsed);

}

现在结果如下。因此,使用 IQueryable 进行枚举似乎对性能产生了初步影响,但当您调用以后的搜索时,事情似乎会加快,即

*****************
Deleting all records: 00:00:00.0670336
*****************
Created: 30k rows: 00:00:04.6829844
*********************
* IQueryable & LINQ *
*********************
Find one from start: 00:00:00.0878309
Find one from start: 00:00:00.0120098
Find one from end: 00:00:00.0116334
Find in loop of 50: 00:00:00.5890532
*****************
* List & Filter *
*****************
Find one from start: 00:00:00.0248407
Find one from end: 00:00:00.0118345
Find in loop of 50: 00:00:00.5377828
*****************
Deleting all records: 00:00:00.7029368

最佳答案

您最初的问题是为什么 LINQ 比使用 API 快得多。该问题的答案是因为 LINQ 是延迟(惰性)执行的,并且查询实际上并未完成。在您实际尝试迭代结果(foreach/.ToList()/etc)之前,查询不会完成。

您可能选择了此声明的时间:

IQueryable<Client> asd4 = collection.SearchFor().Where(x => x.ClientDesc == "<search text>");

当你应该安排这个陈述的时间时:

List<Client> asd4 = collection.SearchFor().Where(x => x.ClientDesc == "<search text>").ToList();

您在更新期间显示的性能数字似乎很合理。 LINQ 实际上比使用直接 API 稍慢,因为它为查询添加了抽象。这种抽象允许您轻松地将 MongoDB 更改为另一个数据源(SQL Server/Oracle/MySQL/XML/等),而无需更改大量代码,但您为此抽象付出的代价是轻微的性能损失。

关于c# - MongoDB C# 驱动程序 : API vs Linq Performance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34610554/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com