ServiceStack занимает много времени для выполнения хранимой процедуры

Я реализовал ServiceStack (v4.0.36) с подключением ORMLite к моей базе данных SQL Server 2014. На моем веб-сайте есть форма поиска, которая передает любые заполненные поля маршруту «/search» в качестве параметров строки запроса. Мой запрос DTO выглядит так:

[Route("/search", "GET")]
public class SearchRequest
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    ...
}

(всего 8 параметров). Затем у меня есть служба, которая вызывает хранимую процедуру в SQL, передавая все такие параметры, как:

public class MyServices : Service
{
    public object Get(SearchRequest request)
    {
        using (var db = AppHostBase.Instance.Container.TryResolve<OrmLiteConnectionFactory>().OpenDbConnection())
        {
            List<SearchResponse> searchResults = db.SqlList<SearchResponse>("EXEC sp_web_ResultListByNameOrAddress @firstName, @lastName, ...",
                new
                {
                    firstName = request.FirstName,
                    lastName = request.LastName,
                    ...
                });

            return searchResults;
        }
    }
}

Проблема в том, что если я выполняю поиск на веб-сайте, для получения результатов требуется до 30 секунд (или время истекает, и соединение обрывается). Если я выполняю ту же хранимую процедуру в SQL, я получаю результаты мгновенно (индексируются поля поиска и комбинации).

Я заметил некоторый прирост производительности после изменения моего web.config

<compilation targetFramework="4.5" debug="false"/>

... но я все еще не понимаю, где происходит узкое место. Любая помощь будет принята с благодарностью!

на на на на на на на на ... Бэтмен! ?

ОБНОВЛЕНИЕ. К вашему сведению, я подключаюсь к этой службе через отдельное веб-приложение AngularJS, но также получаю проблемы с медлительностью или тайм-аутом при тестировании службы через клиент REST, такой как Postman. Спасибо.

ОБНОВЛЕНИЕ 2: я включил мини-профилировщик... задержка на этапе «Выполнение службы». Вот пример поискового запроса:

Мини-скриншот профайлера

Я собираюсь включить профилирование SQL в соединении ORMLite и опубликовать все обновления.

ОБНОВЛЕНИЕ 3: Не очень полезно (я думаю)... SQL Profiler просто показывает сохраненный процесс, который был выполнен:

Профилировщик SQLМини-профилировщик с добавленным SQL

ОБНОВЛЕНИЕ 4: Интересно. Таким образом, у меня есть профилировщик SQL Server SSMS, работающий вместе с моим запросом с включенным мини-профилировщиком, и я также устанавливаю точку останова в реализации службы на строке, которая запускает хранимую процедуру.

Когда я загружаю страницу, сразу же срабатывает точка останова. Когда я продолжаю, я вижу сообщение «Аудит входа в систему» ​​в SQL Server Profiler. Затем ничего в течение нескольких минут, затем сообщение «RPC: Completed» с сохраненным процессом и переданными аргументами.

Таким образом, запрос не попадает в SQL до самого конца, где он возвращается почти сразу (как и следовало ожидать). Почему существует большая задержка между отправкой запроса ServiceStack и его фактическим выполнением на SQL Server? Все локально, поэтому я не вижу проблемы с сетью. Кто-нибудь?


person ItJustWerks    schedule 26.01.2015    source источник


Ответы (2)


Нашел эту ссылку, и она решила мою проблему: take-longer">Что происходит в отладочной компиляции, из-за чего выполнение запроса занимает больше времени?

У меня был тип данных bigint, возвращаемый хранимой процедурой, которая сопоставлялась со строковым типом данных в моем ответе службы POCO. Я добавил оператор CONVERT(varchar...) в хранимую процедуру, и теперь все работает намного быстрее. Спасибо!

Повторное открытие! Извините, что так легкомысленно отношусь к этому. Моя единственная форма отправляет все параметры хранимой процедуре. Я только что увеличил время ожидания ORMLiteConfig до 500 секунд и заметил, что некоторые поиски занимают около 4 минут. Опять же, выполнение того же действия в SSMS мгновенно возвращает результаты. Что происходит??

person ItJustWerks    schedule 26.01.2015
comment
У медленных поисков большое количество результатов? Или они медленные с малым количеством результатов? Это укажет, является ли узким местом этап выполнения SQL/ADO, этап копирования в DTO, этап сериализации в JSON или передачу по сети HTTP. - person Raul Nohea Goodness; 28.01.2015
comment
См. обновления к моему исходному сообщению для получения результатов от мини-профилировщика ServiceStack, но результаты, как правило, представляют собой одну строку. - person ItJustWerks; 28.01.2015
comment
Да я вижу. На этом этапе я бы попытался использовать тот же db/IDbConnection, но попытался выполнить традиционное выполнение типа SqlCommand StoredProc с помощью SqlDataReader. Мне было бы интересно узнать, связана ли проблема с выполнением ADO или с кодом OrmLite. - person Raul Nohea Goodness; 28.01.2015

Добавление дополнительного ответа, потому что на самом деле было две проблемы. Настоящий корень, похоже, связан с хранимой процедурой. Я не знаю, почему это не всегда вызывало проблемы, но я перестроил его с помощью динамического SQL, чтобы включить фильтры WHERE только для имеющихся параметров. Изначально у меня было что-то вроде этого:

CREATE [sp_name]
    @Name varchar(60) NULL,
    @Address varchar(150) NULL
    ...
AS
BEGIN
    SELECT *
    FROM tbl_A a
    WHERE (@Name IS NULL OR a.Name = @Name)
        AND (@Address IS NULL OR a.Address = @Address)

Я думал, что оператор «ИЛИ» сначала оценит первую половину и никогда не попытается оценить вторую половину, если первая была ложной. Может это не так работает? В любом случае я переписал это так:

CREATE [sp_name]
    @Name varchar(60) NULL,
    @Address varchar(150) NULL
    ...
AS
BEGIN
    DECLARE @SQL NVARCHAR(4000);
    DECLARE @ParamDef NVARCHAR(4000);

    SELECT @ParamDef = ' 
        @NameParam varchar(60), 
        @AddressParam varchar(150),
    ';

    SELECT @SQL = N'
        SELECT *
        FROM tbl_A a
        WHERE 1=1';

    IF @Name IS NOT NULL
        SELECT @SQL = @SQL + N'
            AND a.Name = @NameParam ';

    IF @Address IS NOT NULL
        SELECT @SQL = @SQL + N'
            AND a.Address = @Address ';

    EXEC sp_executeSQL
        @SQL,
        @ParamDef,
        @NameParam = @Name,
        @AddressParam = @Address;
END

Теперь работает намного лучше. Спасибо!

person ItJustWerks    schedule 28.01.2015
comment
Значит, это означает, что оператор короткого замыкания доставляет вам проблемы. Проверьте weblogs.sqlteam.com/jeffs /архив/22 февраля 2008 г./ - person Kamran Shahid; 03.02.2015