Свободный запрос nhibernate занимает много времени для сортировки сопоставленной формулы с подкачкой - PullRequest
2 голосов
/ 29 марта 2012

У нас есть сетка данных для отображения записей участников для наших клиентов.Недавно нам было поручено добавить пейджинг в наше приложение, чтобы наши крупные клиенты (более 500 000 участников).

Наша таблица, из которой мы получаем данные, имеет 10 столбцов.При извлечении наших данных в наше приложение мы добавили 3 дополнительных столбца, которые все являются вычисляемыми полями

т.е.

SELECT SUM(tableX.Cost) FROM tableX WHERE tableX.ID = this_.ID

, где "this_" - это псевдоним для нашей таблицы членов, а tableX представляет другую таблицу.что нам нужно получить данные из.

В нашем запросе мы должны предоставить возможность упорядочить столбцы, но я заметил, что когда я пытаюсь упорядочить вычисляемые поля, это занимает значительное количество времени по сравнениюкогда я заказываю столбец, который существует в таблице.Это имеет смысл, так как это занимает больше времени, но когда требуется несколько минут, чтобы загрузить только 1000 записей, и будет более 500 страниц для просмотра.Тогда я чувствую, что это делает бессмысленным подкачку страниц.

Я немного подумал, возможно, делаю кэш 2-го уровня с помощью nhibernate, но из того, что я прочитал до сих пор, я не уверен, решит ли эту проблему.

Кстати, одна из карт:

Map(x => x.Cost)
    .Formula(@"(SELECT SUM(_Claims.Cost) FROM _Claims WHERE _Claims.ID = this_.ID")
    .Nullable();

и для запроса

    var list = CurrentSession()
               .SetFirstRsult(startPos)
               .SetMaxResults(1000)
               .SetTimeout(100)
               .Add(Restrictions.Eq("ClientID", _clientID));

    if(isASC)
    {
        list.AddOrder(Order.Asc(Projetions.Property(_propertyString)));
    }
    else
    {
        list.AddOrder(Order.Desc(Projetions.Property(_propertyString)));
    }

    return list.List<Member>();

У меня заканчиваются идеи для этого.Так что, если кто-то может указать нам правильное направление, я буду очень признателен.

Спасибо

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

На самом деле это не столько проблема NHibernate, сколько общая проблема SQL.

Конечно, он сортируется на сервере, но сумма будет рассчитана для всех записей, прежде чем они могут быть отсортированы. Вы должны быть в состоянии проверить это, используя профилировщик SQL или создав функцию / процедуру SQL, которая вычисляет сумму и вставляет ее в ваш запрос, а затем проверяет, как часто он вызывается. Если у вас есть стол с 500 000+ участниками, он будет вызываться 500 000+ раз; Обойти это просто невозможно.

Что вы можете попробовать это:

  1. Убедитесь, что вы используете индекс для Claims.ID (внешний ключ помогает).
  2. Скопируйте и вставьте сгенерированный SQL и запустите его непосредственно в базе данных и посмотрите, займет ли это много времени.
  3. Если вы не возражаете против некоторой формы избыточности, вы можете добавить новые столбцы для вычисляемых полей в таблицу Members и использовать триггеры (вставка / удаление) в таблице Claims, чтобы соответствующим образом обновить эти столбцы.
  4. Если вы не хотите использовать триггеры, вы можете также создать запланированное событие базы данных, чтобы выполнить расчет. (Конечно, это будет вариант, если вам не нужны данные в режиме реального времени).
0 голосов
/ 04 апреля 2012
  1. Первый вариант - предварительно рассчитать данные и подготовить их для запроса из таблицы.
  2. Создать представление и сопоставить его с объектом передачи данных.В представлении вы можете сначала ограничить набор данных, а затем выполнить расчет.Меньшее количество данных для расчета ускоряет выполнение вашего запроса.
...