我的查询在 SSMS 中很快,但在我的应用程序中超过 1 小时
Posted
技术标签:
【中文标题】我的查询在 SSMS 中很快,但在我的应用程序中超过 1 小时【英文标题】:my query is fast in SSMS but goes over 1 hour in my app 【发布时间】:2018-11-07 22:50:46 【问题描述】:我的应用程序中的查询速度很慢,但在 SSMS 中查询速度非常快。看到一些答案后,我注意到执行计划似乎有所不同。
我注意到,当我使用 SSMS 时,使用了称为 [Parallelism (Repartition Streams)] 的东西,但我在来自 C# 应用程序的执行计划中没有看到它(我在 SSMS 中使用 Activity Monitor 来查看)。此外,当我使用我的应用程序时,我看到查询列在“Active Expensive Queries”列表中,但当我从 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
的部分,我很快就在应用程序中得到了结果!但这不是我想要的结果。这对我来说真的很重要。
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 运行查询时相同。
有什么想法吗?
编辑:
我的 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();
【问题讨论】:
评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:根据您对其他答案的评论,如果您只是想获取每个 recycler_id 的最新 TRANS_ID,您可以使用下面的查询来完成。这假设您的 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
【讨论】:
【参考方案2】:我试图重写查询,但没有数据我不确定我是否正确
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
【讨论】:
我明天就可以测试了。我想要对查询执行的操作是获取每个 Recycler 的最新交易,这就是为什么我使用 'OVER(PARTITION BY t.RECYCLER_ID) AS _max' 如果这就是你想要做的,你通常可以用左连接来做到这一点。但是您是否尝试将您的 where sub select 移动到 join sub select? @Neil.Work 将在早上尝试这第一件事我下班了哈哈 @Neil.Work 我在这里看不到优势,但可以肯定的是,您可以做到。 这更快(20 秒),但我想我找到了主要原因。在我的连接字符串中,我将 Initial Catalog 设置为数据库 D,而在此查询中也使用了数据库 S。在我从连接字符串中删除它之后,它是即时的!上面的 cmets 中有人提到了连接字符串部分。如果他把这个作为答案,我想我可以接受。以上是关于我的查询在 SSMS 中很快,但在我的应用程序中超过 1 小时的主要内容,如果未能解决你的问题,请参考以下文章
SP 在强大的服务器上很慢,但在本地很快(都来自 SSMS)