SortedSet <T> содержит по сравнению с запросом Linq

У меня есть очень простой SortedSet с методом CompareTo что виды на основе двух полей класса. Поскольку это используется, этот набор может стать довольно большим (миллион + объекты) и растет и растет со временем. Я использовал простое, Содержит метод, чтобы определить, существует ли новое значение уже в наборе...

Как академическое осуществление я делаю некоторое использование сравнительных тестов Linq (который я довольно плохо знаком для) достигнуть того же эффекта, и уверено, что существует некоторое понимание Linq, что мне недостает, потому что я не могу приехать удаленно близко к той же производительности, и я задавался вопросом, мог ли некоторый гуру Linq дать мне подсказку по тому, что могло бы быть сделано для ускорения его.

Так... Объект имеет CompareTo, который выглядит примерно так:

public int CompareTo(EntityHistoryChange other)
{
    int recordIdComp = Recordid.CompareTo(other.Recordid);
    int tableIdComp = Tablename.CompareTo(other.Tablename);

    if (recordIdComp == 0 && tableIdComp == 0)
        return 0;
    else if (recordIdComp != 0)
        return recordIdComp;
    else
        return tableIdComp;
}

Соответствующие Linq запрашивают в простом Списке:

var handledChange = from thisChange in handledChanges
                    where thisChange.Recordid == recordId 
                      && thisChange.Tablename == tableName
                    select thisChange;

Я предполагаю, что результаты не должны удивлять меня...

Linq Lookup on 18772 rows: 46 ms
SortSet Lookup on 18772 rows: 3 ms

Таким образом, вопрос - каков эквивалентный механизм LINQ?

1
задан µBio 5 August 2010 в 17:05
поделиться

3 ответа

Linq никогда не будет таким быстрым, поскольку объект, который видит Linq, - это не SortedSet, а IEnumerable , который не имеет другой семантики, кроме «Дайте мне список объектов». Вы вообще не пользуетесь Сетью.

По какому ключу выполняется сортировка SortedSet ? Разве это не было бы просто поиском через SortedSet.Contains, после чего вы могли бы проверить имя таблицы?

2
ответ дан 2 September 2019 в 22:24
поделиться

Многие операторы LINQ проверяют наличие интерфейсов за пределами IEnumerable и используйте их.

Например. Count будет проверять ICollection и использовать его свойство Count, а не выполнять итерацию по всей коллекции. Единственный способ увидеть это (вне тестов) - посмотреть на IL (или использовать Refector), и, конечно, реализация может измениться с новой версией .NET (включая SP). Например. в .NET r.5 Count не проверял ICollection , но проверял в 4.

0
ответ дан 2 September 2019 в 22:24
поделиться

LINQ не предназначен для замены использования правильных структур данных для конкретной работы. Он просто упрощает работу с этими структурами данных. Если вы храните данные в базе данных SQL, от вас все равно ожидается использование интеллектуальных индексов в вашей базе данных для повышения производительности. Аналогично, в LINQ to Objects вам нужно использовать структуры данных типа SortedSet там, где это необходимо.

Итак, ответ на ваш вопрос: LINQ-запрос, имитирующий метод Contains, будет выглядеть так:

var exists = handledChanges.Any(c => c.Recordid = recordId && c.Tablename == tableName);

Но если вы используете LINQ to Objects, это никогда не достигнет такой же производительности, как использование метода Contains на структуре данных, специально приспособленной для быстрого поиска. Если вы используете LINQ to SQL или LINQ to Entities, это обеспечит оптимизированный SQL-запрос, который может выполняться очень быстро.

Кстати, если ваша цель - получить более быстрый поиск в коллекции в памяти, вы можете рассмотреть возможность использования HashSet с пользовательским IEqualityComparer. Его метод Contains должен занимать столько же времени для коллекции из миллионов объектов, сколько и для коллекции из 10.

0
ответ дан 2 September 2019 в 22:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: