RavenDB плохой выбор производительности - PullRequest
8 голосов
/ 15 января 2012

Я тестирую RavenDB для своих будущих проектов.Производительность базы данных является обязательным требованием для меня, поэтому я хочу иметь возможность настроить RavenDB как минимум на диапазон производительности SQL Server, но мои тесты показывают, что raven db примерно в 10–20 раз медленнее в отдельных запросах, чем SQL Server, дажекогда RavenDB проиндексирован, а SQL Server не имеет индексов.

Я заполнил базу данных 150 тыс. документов.Каждый документ имеет коллекцию дочерних элементов.Размер дб ок.1 ГБ и размер индекса тоже.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 (не знаю, оказывает ли он какое-либо отрицательное / положительное влияние на производительность).

Этот запрос занимает от 500 мс до 1500 мс (обратите внимание, что этовремя, необходимое для выполнения запроса, которое отображается непосредственно из консоли ravendb. Таким образом, оно не содержит времени HTTP-запроса и издержек десериализации. Просто время выполнения запроса.

session.Query<Order>("OrdersIndex").Where(o =>
    o.Items.Any(oi => oi.Price.Amount > 0 && oi.Quantity < 100)).Take(128).ToList();

Я выполняю запрос наЧетырехъядерный процессор i5 работает на частоте 4,2 ГГц, а база данных находится на твердотельном накопителе.

Теперь, когда я заполнил тот же объем данных на сервере sql express, с той же схемой и таким же количеством связанных объектов.без индекса сервер sql выполняет тот же запрос, который включает соединения за 35 мс.С индексом это занимает 0 мс: |.

Все тесты были выполнены при разогреве серверов db.

Хотя я все еще очень доволен производительностью RavenDB, мне интересно, если ячего-то не хватает или RavenDB работает медленнее, чем реляционная база данных?Извините за мой плохой английский.

Спасибо

ОБНОВЛЕНИЕ

Аянде, я попробовал то, что вы предложили, но когда я пытаюсь определить индекс, который вы послалия получаю следующую ошибку:

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: Невозможно использовать лямбда-выражение в качестве аргумента для динамически отправляемой операции без предварительного приведения его к типу дерева делегата или выражения

1 Ответ

6 голосов
/ 17 января 2012

DaVita, Следующий индекс генерирует ~ 8 миллионов записей индекса:

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 }

И может быть запрошен с теми же результатами, но в наших тестах оказался примерно в два раза быстрее.

Основная проблема заключается в том, что вы делаете несколько запросов диапазона, которые являются дорогостоящими с большим количеством потенциальных значений, а затем у вас есть большое количество фактических совпадений для запроса.

Кстати, точное совпадение значительно быстрее.

Мы все еще работаем над тем, чтобы попытаться ускорить процесс.

...