мой запрос в SSMS быстрый, но в моем приложении он занимает более 1 часа - PullRequest
0 голосов
/ 08 ноября 2018

У меня проблема с медленным запросом в моем приложении, но это так быстро в SSMS. После того, как я увидел какой-то ответ, я заметил, что план выполнения выглядит по-другому.

Я заметил, что когда я использую SSMS, что-то называется [Parallelism (Repartition Streams)], но я не вижу его в плане выполнения, поступающем из моего приложения C # (я использую Activity Monitor в SSMS, чтобы увидеть это). Кроме того, когда я использую свое приложение, я вижу, что запрос указан в списке «Активные дорогие запросы», но это не тот случай, когда я запускаю его из SSMS.

Я добавлю свой запрос, но постараюсь скрыть текст только для конфиденциальности моей компании:

SELECT  [REC_INVENT_LIST_ID]
      , ril.[NOTE_TYPE_ID]
      , ril.[TRANS_ID] 
      , [QUANTITIES]
      , [AMOUNT]
      , nt.[CU_TYPE]
      , nt.[CASH_TYPE]
      , nt.[NOTE_VALUE]
      , nt.[UNIT_ID]
      , t.RECYCLER_ID
FROM [D].[dbo].[RecyclerInventoryList] ril
JOIN [S].[dbo].[NoteType] nt ON nt.NOTE_TYPE_ID = ril.NOTE_TYPE_ID
JOIN [D].[dbo].[Transaction] t ON ril.TRANS_ID = t.TRANS_ID
WHERE QUANTITIES <> 0
AND ril.TRANS_ID IN (
        SELECT sub.TRANS_ID FROM (SELECT *, MAX(CREATE_DATE) 
        OVER(PARTITION BY t.RECYCLER_ID) AS _max
        FROM [D].[dbo].[Transaction] AS t
        WHERE TRANS_ID <= @lastTransId) AS sub
        WHERE CREATE_DATE = _max
                 )
ORDER BY t.RECYCLER_ID, CU_TYPE 

То, что я сделал, это:

1- Я попытался удалить часть, в которой написано WHERE TRANS_ID <= @lastTransId, чтобы убедиться, что это не проблема преобразования параметров, но это не помогло.

2- Я удалил часть, где написано WHERE CREATE_DATE = _max Я получил результат обратно в приложение FAST !, но это не тот результат, который я хочу. Это где действительно важно для меня.

3 - Я использовал SQL SERVER PROFILER, чтобы увидеть, какой именно запрос пытается выполнить после истечения времени ожидания и сбоя моего приложения (1 час команды). Я вижу это так

exec sp_executesql N'SELECT [REC_INVENT_LIST_ID], ril.[NOTE_TYPE_ID], ril.[TRANS_ID], [QUANTITIES], [AMOUNT], nt.[CU_TYPE], nt.[CASH_TYPE], nt.[NOTE_VALUE], nt.[UNIT_ID], t.[RECYCLER_ID] FROM[RCMDYNAMIC].[dbo].[RecyclerInventoryList] ril JOIN[RCMSTATIC].[dbo].[NoteType] nt ON nt.NOTE_TYPE_ID = ril.NOTE_TYPE_ID JOIN[RCMDYNAMIC].[dbo].[Transaction] t ON ril.TRANS_ID = t.TRANS_ID  WHERE QUANTITIES<> 0 AND ril.TRANS_ID IN (SELECT sub.TRANS_ID FROM (SELECT TRANS_ID, CREATE_DATE , MAX(CREATE_DATE) OVER(PARTITION BY t.RECYCLER_ID) AS _max FROM[RCMDYNAMIC].[dbo].[Transaction] AS t WHERE TRANS_ID <= @lastTransId ) AS sub WHERE CREATE_DATE = _max) ORDER BY t.RECYCLER_ID, CU_TYPE',N'@lastTransId int',@lastTransId=XXXXX

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

Есть идеи?

EDIT:

Мой код C #:

public Dictionary<int, List<RCMBalanceTransactionModel>> getBalanceTransactions(int transId) {

        SqlCommand command;
        SqlDataReader reader;
        command = new SqlCommand(getBalanceTransactionInfoQuery(), con);
        command.CommandTimeout = 3600;
        command.Parameters.AddWithValue("@lastTransId", transId);
        reader = command.ExecuteReader();


  //the rest is omitted the application is stuck here at ExecutedReader();
}

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

На основании вашего комментария из другого ответа, если вы просто пытаетесь получить последний TRANS_ID для recycler_id, вы, вероятно, могли бы сделать это с помощью запроса ниже. Это предполагает, что ваши идентификаторы генерируются по порядку. Вы также можете сделать то же самое с CREATE_DATE, если вы уверены, что две транзакции одного и того же переработчика не имеют одинаковый CREATE_DATE. Я не уверен в вашей цели @lastTransId, поэтому вам может потребоваться добавить это в предложение where.

SELECT  
    [REC_INVENT_LIST_ID]
      , ril.[NOTE_TYPE_ID]
      , ril.[TRANS_ID] 
      , [QUANTITIES]
      , [AMOUNT]
      , nt.[CU_TYPE]
      , nt.[CASH_TYPE]
      , nt.[NOTE_VALUE]
      , nt.[UNIT_ID]
      , t.RECYCLER_ID
FROM 
    [D].[dbo].[RecyclerInventoryList] ril
    JOIN [S].[dbo].[NoteType] nt 
        ON nt.NOTE_TYPE_ID = ril.NOTE_TYPE_ID
    JOIN [D].[dbo].[Transaction] t 
        ON ril.TRANS_ID = t.TRANS_ID
    LEFT OUTER JOIN [D].[dbo].[Transaction] t2
        ON t.RECYCLER_ID = t2.RECYCLER_ID AND t.TRANS_ID < t2.TRANS_ID
WHERE
    t2.TRANS_ID IS NULL AND /* This is null only for t.TRANS_ID that have no records greater than itself, ie the latest one */
    QUANTITIES <> 0
ORDER BY 
    t.RECYCLER_ID, CU_TYPE 
0 голосов
/ 08 ноября 2018

Я пытался переписать запрос, но без данных я не уверен, правильно ли я понял

SELECT  [REC_INVENT_LIST_ID]
      , ril.[NOTE_TYPE_ID]
      , ril.[TRANS_ID] 
      , [QUANTITIES]
      , [AMOUNT]
      , nt.[CU_TYPE]
      , nt.[CASH_TYPE]
      , nt.[NOTE_VALUE]
      , nt.[UNIT_ID]
      , t.RECYCLER_ID
FROM [D].[dbo].[RecyclerInventoryList] ril
JOIN [S].[dbo].[NoteType] nt ON nt.NOTE_TYPE_ID = ril.NOTE_TYPE_ID
JOIN [D].[dbo].[Transaction] t ON ril.TRANS_ID = t.TRANS_ID
WHERE QUANTITIES <> 0
AND t.TRANS_ID <= @lastTransId
AND NOT EXISTS(SELECT 1 FROM [D].[dbo].[Transaction] AS t2 
    WHERE t2.RECYCLER_ID = t.RECYCLER_ID 
      AND t2.CREATE_DATE > t.CREATE_DATE 
          AND t2.TRANS_ID <= @lastTransId)

ORDER BY t.RECYCLER_ID, CU_TYPE 
...