【发布时间】:2012-06-14 19:21:53
【问题描述】:
我有一个转换实用程序,基本上可以将值从一个表复制到另一个表。一段时间以来效果很好,但我遇到了一位客户的奇怪问题。他们使用该实用程序处理了 150 万条记录,但现在它已完全停止。
从 VB.Net 调用存储过程时,它只是挂起,直到 SqlCommand 超时。从 Management Studio 调用相同的存储过程会立即执行。我的 SqlCommand 的 VB.Net 代码如下(insertConn 是之前定义和打开的,dr 是一个 SqlDataReader,它已在上一步中从完全不同的 SqlConnection 和 SqlCommand 实例中填充):
Dim conn As New SqlConnection("connection string here")
Dim insertConn As New SqlConnection("connection string here")
Dim dr As SqlDataReader = Nothing
Dim readCommand As New SqlCommand("my query here", conn)
conn.Open()
insertConn.Open()
...
dr = readCommand.ExecuteReader()
...
While dr.Read()
Using insertCommand = New SqlCommand("dmDocumentFieldInsert", insertConn)
insertCommand.CommandType = CommandType.StoredProcedure
insertCommand.Parameters.AddWithValue("@DocumentKey", dr("DocumentKey"))
insertCommand.Parameters.AddWithValue("@FieldId", "TITLE")
insertCommand.Parameters.AddWithValue("@FieldValue", dr("DocumentTitle"))
insertCommand.ExecuteNonQuery()
End Using
End While
我尝试重新启动 SQL Server 以清除所有锁定、重新编译存储过程、增加 SqlCommand 和 SqlConnection 超时,但均无济于事。
我检查了添加到参数中的数据,它是有效数据...如果我使用相同的数据手动调用存储过程,它可以正常工作。
我最初没有使用 Using 块,但更改了它以查看是否有一些资源问题没有得到处理/关闭。该实用程序的内存使用量徘徊在 5MB 左右,因此似乎没有任何内存问题。
有没有人对下一步尝试解决方案有什么建议?
编辑为每个评论请求添加循环和初始化代码
EDIT我更新了统计信息并重建了表索引,没有任何变化。
EDIT 数据被复制到的表上有三个索引(dmDocumentField)。如果我禁用所有三个索引,则存储过程会完美执行,尽管比索引存在时慢得多。如果我启用其中任何一个,那么该实用程序最多可以通过几百条记录,然后在 sproc 上以相同的超时终止。删除并重新创建索引无效。表结构和索引如下:
CREATE TABLE [dbo].[dmDocumentField](
[FieldKey] [bigint] IDENTITY(1,1) NOT NULL,
[DocumentKey] [char](36) NOT NULL,
[FieldId] [varchar](10) NOT NULL,
[FieldValue] [varchar](255) NOT NULL,
CONSTRAINT [PK_dmDocumentField] PRIMARY KEY NONCLUSTERED
(
[FieldKey] ASC,
[DocumentKey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
索引(除了 PK):
CREATE NONCLUSTERED INDEX [dmDocumentField_DocumentKey] ON [dbo].[dmDocumentField]
(
[DocumentKey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
.
CREATE NONCLUSTERED INDEX [dmDocumentField_DocumentKey_IFieldId_IFieldValue] ON [dbo].[dmDocumentField]
(
[DocumentKey] ASC
)
INCLUDE ( [FieldId],
[FieldValue]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
【问题讨论】:
-
我还要提一下,该实用程序位于 VB.Net 4 中,而相关的 SQL Server 是 SQL Server 2008 R2 Standard。
-
SQL 分析器有什么异常吗?
-
您可以尝试使用Enterprise Library中的数据访问方法。
-
这段代码是在循环中调用的吗?如果是的话,你能不能也显示循环代码?
-
如果你使用 .AddWithValue ,那么 SQL Server 会为每个不同大小的参数生成一个不同的执行计划(根据我自己的测试)。如果您在创建 SQL 参数时设置了 .Size,那么您只会得到一个执行计划。
标签: vb.net stored-procedures sqlcommand