我正在为我未来的项目测试RavenDB。数据库性能对我来说是一个必须的要求,这就是为什么我希望能够将RavenDB调整到至少在SQL Server的性能范围内,但我的测试表明,即使RavenDB是索引的,SQL Server没有任何索引,RavenDB在选择查询中的速度也比SQL Server慢大约10x-20倍。
我用15万个文档填充了数据库。每个文档都有一个子元素的集合。Db大小约为1GB,索引大小也是如此。Raven/Esent/CacheSizeMax设置为2048,Raven/Esent/MaxVerPages设置为128。以下是文档的样子:
{
"Date": "2028-09-29T01:27:13.7981628",
"Items": [
{
{
"ProductId": "products/673",
"Quantity": 26,
"Price": {
"Amount": 2443.0,
"Currency": "USD"
}
},
{
"ProductId": "products/649",
"Quantity": 10,
"Price": {
"Amount": 1642.0,
"Currency": "USD"
}
}
],
"CustomerId": "customers/10"
}
public class Order
{
public DateTime Date { get; set; }
public IList<OrderItem> Items { get; set; }
public string CustomerId { get; set; }
}
public class OrderItem
{
public string ProductId { get; set; }
public int Quantity { get; set; }
public Price Price { get; set; }
}
public class Price
{
public decimal Amount { get; set; }
public string Currency { get; set; }
}
这是定义的索引:
from doc in docs.Orders
from docItemsItem in ((IEnumerable<dynamic>)doc.Items).DefaultIfEmpty()
select new { Items_Price_Amount = docItemsItem.Price.Amount, Items_Quantity = docItemsItem.Quantity, Date = doc.Date }
我使用Management studio定义了索引,而不是来自代码BTW(不知道它是否对perfromance有任何负面/正面影响)。
这个查询需要500ms到1500ms才能完成(请注意,这是执行查询所需的时间,直接从ravendb的控制台显示。因此,它不包含http请求时间和反序列化开销。只包含查询执行时间)。
session.Query<Order>("OrdersIndex").Where(o =>
o.Items.Any(oi => oi.Price.Amount > 0 && oi.Quantity < 100)).Take(128).ToList();
我在4.2 GHz的四核i5 cpu上运行查询,数据库位于SSD上。
现在,当我在sqlserverexpress上填充相同数量的数据时,使用相同的模式和相同数量的关联对象。在没有索引的情况下,sqlserver执行相同的查询,其中包括35ms中的联接。使用索引需要0ms:|。
所有测试都是在数据库服务器预热时执行的。
尽管如此,我仍然对RavenDB的性能非常满意,我很好奇是我遗漏了什么,还是RavenDB比关系数据库慢?抱歉我英语不好。
感谢
更新
Ayande,我试过你的建议,但当我试图定义你发给我的索引时,我得到了以下错误:
public Index_OrdersIndex()
{
this.ViewText = @"from doc in docs.Orders
select new { Items_Price_Amount = doc.Items(s=>s.Price.Amount), Items_Quantity = doc.Items(s=>s.Quantity), Date = doc.Date }
";
this.ForEntityNames.Add("Orders");
this.AddMapDefinition(docs => from doc in docs
where doc["@metadata"]["Raven-Entity-Name"] == "Orders"
select new { Items_Price_Amount = doc.Items(s => s.Price.Amount), Items_Quantity = doc.Items.(s => s.Quantity), Date = doc.Date, __document_id = doc.__document_id });
this.AddField("Items_Price_Amount");
this.AddField("Items_Quantity");
this.AddField("Date");
this.AddField("__document_id");
this.AddQueryParameterForMap("Date");
this.AddQueryParameterForMap("__document_id");
this.AddQueryParameterForReduce("Date");
this.AddQueryParameterForReduce("__document_id");
}
}
错误CS1977:如果不首先将lambda表达式强制转换为委托或表达式树类型,则无法将其用作动态调度操作的参数
Davita,以下索引生成约800万个索引条目:
from doc in docs.Orders
from docItemsItem in ((IEnumerable<dynamic>)doc.Items).DefaultIfEmpty()
select new { Items_Price_Amount = docItemsItem.Price.Amount, Items_Quantity = docItemsItem.Quantity, Date = doc.Date }
这一次生成的更少:
from doc in docs.Orders
select new { Items_Price_Amount = doc.Items(s=>s.Price.Amount), Items_Quantity = doc.Items.(s=>s.Quantity), Date = doc.Date }
并且可以用相同的结果进行查询,但在我们的测试中,速度大约是原来的两倍。
主要的问题是,您正在进行几个范围查询,这些查询的成本很高,有大量的潜在值,然后您有大量的实际匹配项。
顺便说一句,进行精确匹配要快得多。
我们仍在设法加快速度。