Очень медленный поиск простого отношения сущности - PullRequest
0 голосов
/ 22 февраля 2012

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

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

Этот бит прост и работает довольно хорошо и моделируется в 3 пользовательских объекта.

Теперь у нас есть приложение администратора, которое читает комнаты и затем хочет показать курсы для этой комнаты, но только там, где есть зачисленные студенты.

В SQL это упрощается до:

SELECT DISTINCT r.CourseName, r.OtherInformation
FROM Rooms r
  INNER JOIN Students S
    ON S.CourseId = r.CourseId
WHERE r.RoomId = @RoomId

И это действительно очень близко к возможному SQL, который генерирует CRM. Мы используем Crm QueryEntity, Filter и LinkEntity для представления этой же структуры.

Проблема теперь состоит в том, что CRM нормализует объект настройки в Базовую таблицу, в которой есть стандартные данные объекта CRM, которые все совместно используют, а затем в таблице ExtensionBase, которая имеет наши настройки. Чтобы предоставить плоский доступ к этому, он создает представление, которое объединяет обе таблицы. Это представление используется в Сгенерированном SQL.

Теперь у базовых таблиц есть индексы, а у представления - нет.

Проблема, с которой мы столкнулись, заключается в том, что все, что мы хотим сделать, - это возвращать курсы, в которых удовлетворено внутреннее соединение, достаточно доказать, что есть записи, а CRM делает его SELECT DISTINCT, поэтому мы возвращаем только один элемент для Room. Сначала это работало на отлично, но теперь у нас тысячи запросов, это занимает более 30 секунд и, конечно, вызывает таймаут во всем, кроме SMS.

Мне дано поверить, что мы можем создавать и изменять индексы для таблиц в CRM, и это не считается неподдерживаемой модификацией; а как насчет просмотров? Я знаю, что если мы изменим сущность, то ее представления воссоздаются, что, конечно, заставит нас переделать наши индексы, когда это произойдет.

Есть ли способ подсказать CRM4.0, что нам нужен определенный индекс?

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

Я подумал о том, чтобы поместить в него новую сущность, в которой есть только RoomId, CourseId и Enrollment Count, но это похоже на невероятную хакерскую игру; В конце концов, индекс разрешил бы необходимость дублирования этих данных и имел бы некоторый триггер, который обновляет данные после каждой операции студента.

И наконец, хотя я знаю, что в данный момент мы застряли на CRM4, можно ли ожидать такого решения в CRM2011? Это, безусловно, добавило бы вес к обновлению этого 5-летнего аргумента продукта.

Ответы [ 3 ]

1 голос
/ 22 февраля 2012

Поскольку представления являются «динамическими» (концептуально, их содержимое генерируется на лету из базовых таблиц каждый раз, когда они используются), они, как правило, не могут быть проиндексированы. Однако SQL Server поддерживает нечто, называемое «индексированное представление». Вам необходимо создать уникальный кластеризованный индекс в представлении, и анализатор запросов должен иметь возможность использовать его для ускорения вашего объединения.

1 голос
/ 22 февраля 2012

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

FetchXml имеет агрегацию, но планы выполнения запросов по-прежнему используют представления: вот SQL, сгенерированный из простого числа выборок из инцидента:

'select 
top 5000 COUNT(*) as "rowcount"
, MAX("__AggLimitExceededFlag__") as "__AggregateLimitExceeded__" from (select top 50001 case when ROW_NUMBER() over(order by (SELECT 1)) > 50000 then 1 else 0 end as "__AggLimitExceededFlag__" from Incident as "incident0"  ...

Я не вижу поддерживаемого решения вашей проблемы.

Если вы создаете приложение для внешнего администратора и используете CRM 4 локально, вы можете перейти к базе данных для запроса, минуя API-интерфейс CRM. Не поддерживается, но позволит решить проблему.

0 голосов
/ 23 февраля 2012

Я собираюсь добавить это как потенциальный ответ, хотя я не верю, что это устойчивое или действительно действительное долгосрочное решение.

После анализа индексов, которые CRM определил автоматически, я понял, чтовыбора дополнительной информации в моем запросе было бы достаточно для удовлетворения требований к столбцам индекса, и теперь запрос выполняется менее чем за секунду.

...