我们决定在游戏中使用mongo db作为实时数据库,但搜索结果的性能是不可接受的。这些是15.000个文档和17个字段(字符串,整数,浮点数)的测试结果
// 14000 ms
MongoUrl url = new MongoUrl("url-adress");
MongoClient client = new MongoClient(url);
var server = client.GetServer();
var db = server.GetDatabase("myDatabase");
var collection = db.GetCollection<PlayerFields>("Player");
var ranks = collection.FindAll().AsQueryable().OrderByDescending(p=>p.Score).ToList().FindIndex(FindPlayer).Count();
这是最糟糕的。 //。ToList()用于测试目的。不要在生产代码中使用。
第二次测试
//9000 ms
var ranks = collection.FindAll().AsQueryable().Where(p=>p.Score < PlayerInfos.Score).Count();
第三次测试
//2000 ms
var qq = Query. GT("Kupa", player.Score);
var ranks = collection.Find( qq ).Where(pa=>(pa.Win + pa.Lose + pa.Draw) != 0 );
还有其他方法可以使用C#.Net 2.0在mongo中进行快速搜索。我们希望根据用户得分获得玩家的等级并对其进行排名。
答案 0 :(得分:2)
要注意这一点,我几年来一直不是.NET开发人员,所以如果c#驱动程序出现问题,我就不能发表评论,但我对Mongo有很好的了解希望我能帮忙......
<强>索引强>
索引会在这里帮到你很多。在对未编制索引的字段进行排序和过滤时,这只会在数据库变大时导致问题。
索引是特定方向的(升序/降序)。这意味着您的“得分”字段应该降序索引:
db.player.ensureIndex({'Score': -1}) // -1 indicating descending
<强>查询强>
此外,Mongo真的很棒(在我看来)并且你看起来并不像是在使用它是最好的能力。
您的第一个电话:
var ranks = collection.FindAll().AsQueryable().OrderByDescending(p=>p.Score).ToList().FindIndex(FindPlayer).Count();
看来(这是我的.NET知识可能让我失望的地方)您正在检索整个集合ToList()
,然后在内存中过滤它(FindPlayer predicate
)以便检索数据子集。我相信这会将整个光标(15.000个文档)评估到应用程序的内存中。
您应该更新您的查询,以便Mongo正在开展工作而不是您的应用程序。
鉴于您的其他查询正在Score
进行过滤,如上所述添加索引应该会大幅提高这些其他查询的效果
<强>仿形强>
如果您在从mongo cli运行时期望进行的调用按预期运行,则可能是驱动程序的查询略有不同。
在mongo CLI中,您首先需要设置分析:
db.setProfilingLevel(2)
然后,您可以查询配置文件集合以查看实际正在进行的查询:
db.system.profile.find().limit(5).sort({ts: -1}).pretty()
这将显示最近的5个电话。