寻找我们服务器最近遇到的性能问题的可能原因(SQL Server 2008),我们发现了一些奇怪的东西:我们的一些系统使用LINQ to SQL来执行SELECT
,INSERT
,{ {1}}和UPDATE
次操作。事实是,如果表具有DELETE
个字段,即使DBML将这些字段映射为varchar
且表字段的大小相同,Linq也会使用varchar
参数生成其查询。例如,我们说我有下一张桌子:
varchar(8000)
该表的DBML设计代码如下所示:
SampleTable
-----------------------------------
Field1 int
Field2 smallint
Field3 varchar(15)
Field4 varchar(50)
在我的程序中,在该表中插入行的方法具有以下代码:
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field1", DbType:="Int NOT NULL")> _
Public Property Field1() As Integer
Get
Return Me._Field1
End Get
Set
If ((Me._Field1 = value) _
= false) Then
Me.OnField1Changing(value)
Me.SendPropertyChanging
Me._Field1 = value
Me.SendPropertyChanged("Field1")
Me.OnField1Changed
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field2", DbType:="SmallInt NOT NULL", IsPrimaryKey:=true)> _
Public Property Field2() As Short
Get
Return Me._Field2
End Get
Set
If ((Me._Field2 = value) _
= false) Then
Me.OnField2Changing(value)
Me.SendPropertyChanging
Me._Field2 = value
Me.SendPropertyChanged("Field2")
Me.OnField2Changed
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field3", DbType:="VarChar(15) NOT NULL", CanBeNull:=false)> _
Public Property Field3() As String
Get
Return Me._Field3
End Get
Set
If (String.Equals(Me._Field3, value) = false) Then
Me.OnField3Changing(value)
Me.SendPropertyChanging
Me._Field3 = value
Me.SendPropertyChanged("Field3")
Me.OnField3Changed
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_Field4", DbType:="VarChar(50) NOT NULL", CanBeNull:=false)> _
Public Property Field4() As String
Get
Return Me._Field4
End Get
Set
If (String.Equals(Me._Field4, value) = false) Then
Me.OnField4Changing(value)
Me.SendPropertyChanging
Me._Field4 = value
Me.SendPropertyChanged("Field4")
Me.OnField4Changed
End If
End Set
End Property
简化了代码
但Linq使用Public Sub InsertOnSampleTable(ByVal intValueForField1 As Integer, ByVal shortValueForField2 As Short, ByVal stringValueForField3 As String, ByVal stringValueForField4 As String)
Dim dataContext as New SampleDataContext
dataContext.Connection.Open()
Dim sampleRow As New SampleTable With _
{.Field1= intValueForField1, _
.Field2 = shortValueForField2, _
.Field3 = stringValueForField3, _
.Field4 = stringValueForField4}
dataContext.SampleTable.InsertOnSubmit(sampleRow)
dataContext.SubmitChanges()
datacontext.Connection.Close()
dataContext.Dispose()
End Sub
参数执行INSERT
:
varchar(8000)
通过互联网查看我发现this post表示它显然是Linq到Sql 4的错误,因为Visual Studio 2008创建的参数大小与DBML中的字段相同。它最终变成this bug report处于关闭状态,并表示该错误无法解决。
现在,虽然我不认为这可能导致我们服务器中出现所有性能问题,但这实际上是否会导致任何性能问题?这种大小变化是否会对实际查询执行产生任何影响?有没有人有这方面的问题和/或找到了解决方法?更多的好奇心而不是其他任何东西,这个 bug 是在更新版本的Visual Studio中解决的吗?我认为这实际上是一种奇怪的行为,如果问题没有得到解决,它会以某种方式使得在DBML中定义varchar字段的大小相当无用。
答案 0 :(得分:0)
只要数据具有相同的基本类型,就不会导致任何性能问题。但请注意类型转换(varchar到nvarchar或nvarchar到varchar),因为它们绝对会破坏性能。
至于定义DBML中的大小是无用的,在某种程度上它是 - 一个包含20个字符的varchar(max)列,占用与varchar(8000)或varchar(20)一样多的空间。不同之处在于,最后一个说明了输入的可接受大小并且允许有效的索引(索引具有900个字符的限制)。
因此,该列的大小对表具有概念性和性能影响,使它们成为适当的大小。对于存储过程或批处理中的局部变量,没有性能影响,对于参数没有性能影响,但存在概念上的影响。
对于LINQ或任何其他ORM,请不要担心大小与此无关,请确保TYPE匹配。