SQL存储过程每25分钟引发一次错误

时间:2016-07-19 18:39:26

标签: sql sql-server vb.net stored-procedures

我有一个存储过程,每25分钟会抛出一个错误。我在应用程序中有代码,当它失败时会向我发送一封电子邮件。我试图确定是否是导致问题的程序本身,或者是否可能与服务器上发生的其他事件发生冲突,或者应用程序中的代码是否可能出错。它本周一直运作良好。我们本周对应用程序进行了更改,并在ADT_Diagnosis表中添加了新代码。自添加代码以来,它一直在抛出错误。所有提示和建议表示赞赏。提前谢谢!

这是它发给我的错误:

  

在护理床服务上发生错误。 “System.Data.SqlClient.SqlException(0x80131904):超时已过期。操作完成之前经过的超时时间或服务器没有响应。在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection)处于System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,布尔breakConnection)的System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()处于System.Data .SqlClient.TdsParser.Run(runBehavior runBehavior,SqlCommand的cmdHandler,SqlDataReader的数据流,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)在System.Data.SqlClient.SqlDataReader.ConsumeMetaData()在System.Data.SqlClient.SqlDataReader.get_MetaData()在System.Data System.Data.SqlClient.SqlCommand.RunExecuteReader(在System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async)中的.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,String resetOptionsString) CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String method,DbAsyncResult result)at System.Data.SqlClient.SqlCommand.ExecuteReader的System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior,String method)中的System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String方法) )Service.MainWindow.TainWindow.TaskThread_DoWork(对象发件人,DoWorkEventArgs e)上的Service.MainWindow.UpdateDataFromADT_Codes(SqlConnection SqlConn)

这是SQL存储过程:

ALTER PROCEDURE GetActivePatientCoreMeasures 
   -- Add the parameters for the stored procedure here
AS
BEGIN
   -- SET NOCOUNT ON added to prevent extra result sets from
   -- interfering with SELECT statements.
   SET NOCOUNT ON;

SELECT DISTINCT ADT.[PV1 Room],adt.[Patient Account Number], 
    [Diagnosis Codes].Description
FROM [CPSISQL].dbo.ADT
LEFT JOIN [CPSISQL].dbo.ADT_Diagnosis 
ON [CPSISQL].dbo.ADT.[Patient Account Number] =
    [CPSISQL].dbo.ADT_Diagnosis.[Patient Account #]
RIGHT JOIN [Diagnosis Codes]
ON ADT_Diagnosis.[Diagnosis Code] = [Diagnosis Codes].Code
WHERE [CPSISQL].dbo.ADT.[PV1 Discharge Date/Time] = ''
AND
(
[CPSISQL].dbo.ADT.[PV1 Department] = '028' OR
[CPSISQL].dbo.ADT.[PV1 Department] = '030' OR
[CPSISQL].dbo.ADT.[PV1 Department] = '032' OR
[CPSISQL].dbo.ADT.[PV1 Department] = '038' OR
[CPSISQL].dbo.ADT.[PV1 Department] = '042' 
)
AND NOT(ADT_Diagnosis.[Diagnosis Type] = 'A')
ORDER BY adt.[PV1 Room]
END

3 个答案:

答案 0 :(得分:1)

您需要排除连接问题。请参阅SQL Connection Error: System.Data.SqlClient.SqlException (0x80131904)

如果这不能解决问题,请从SSMS(SQL Server Management Studio)手动运行存储过程,最好在错误发生后立即运行,并查看返回所需的时间。 VB.NET中的默认命令超时为30秒,因此如果SSMS需要更长时间,则表示您必须增加超时(请参阅Set custom default CommandTimeout for all new Command Objects),或者使存储过程更快。

为了使您的存储过程更快,请从SSMS再次运行它,但这次确保启用了“包括实际执行计划”。这将告诉您查询计划中的哪些操作需要更长时间,甚至可以建议添加到表中的索引以提高性能。

答案 1 :(得分:0)

首先,检查以确保您从运行应用程序的计算机连接到SQL服务器(不要忘记检查应用程序上使用的配置文件)。

它也可能是某种类型的网络块,例如防火墙或需要配置的不同连接类型(命名管道与tcp / ip)。您可以通过SQL Serve Configuration Manager检查SQL Server的配置。

答案 2 :(得分:0)

在不了解您的数据库以及所涉及的表的情况下,很难诊断出您的问题。但是,存储过程中的查询编写起来很奇怪,可能是性能问题的原因。你不知道有多少次我重写了一个丑陋的查询,所有突然的事情开始变得更好。所以我会解决这个问题。

有些事情没有意义:

  • DISTINCT有什么意义。我不知道你的数据库的结构,但它可能是因为如果你把它拿走,你会发现你返回了数百万行,因为你的连接有问题(你的连接肯定有问题) )。
  • LEFT JOIN ADT_Diagnosis ,但 ADT_Diagnosis 也用在WHERE子句中的必需谓词中。因此,如果没有行与来自 ADT_Diagnosis ADT 匹配,那么该谓词将自动为false,并且根本不会返回任何行。您可能在想!='A'将允许NULL值,但NULL既不是='A',也不是!='A',因此它会自动为假。
  • RIGHT JOIN到*诊断代码。在 ADT_Diagnosis 中,如果没有匹配的行,有人可能不希望返回描述。这可能会导致一个大错误。这都是学术性的,因为前一点中提到的谓词将阻止任何行返回。不过,查询计划程序可能会让人感到困惑。
  • NOT(ADT_Diagnosis.[Diagnosis Type] = 'A')不像ADT_Diagnosis.[Diagnosis Type] != 'A'那样容易混淆。
  • 不要多次重复OR,而是使用IN
  • 奖励:随意使用较短的别名而不是表名。它将使查询更容易阅读。

这是在考虑上述要点的情况下重写的查询。因为涉及ADT_Diagnosis的谓词要求从该表返回一行,所以我将连接从LEFTRIGHT更改为INNER,因为该表位于右侧,分别离开了。这解决了第二点和第三点。多个“OR”事件已被删除,并替换为IN

我没有删除DISTINCT,因为我对这些表格知之甚少。我见过许多实例,其中DISTINCT用于修复带有错误连接的查询的结果,因此可能不再需要它。

SELECT DISTINCT adt.[PV1 Room],adt.[Patient Account Number], codes.Description
FROM [CPSISQL].dbo.ADT adt
INNER JOIN [CPSISQL].dbo.ADT_Diagnosis diag
  ON adt.[Patient Account Number] = diag.[Patient Account #]
INNER JOIN [Diagnosis Codes] codes ON diag.[Diagnosis Code] = codes.Code
WHERE adt.[PV1 Discharge Date/Time] = ''
  AND adt.[PV1 Department] IN ('028','030','032', '038', '042')
  AND diag.[Diagnosis Type] != 'A'
ORDER BY adt.[PV1 Room]

这应该返回完全相同的结果,但希望(并且可能)有更好的计划。