我已经彻底测试了在我的应用程序中使用的 VB6 和 ADO 的性能。从记录集中获取数据的绝对最快的方法是使用 FIELD 对象。返回大量行时,您会注意到性能上有很大差异。以下是我的应用程序中的一段代码(简化以突出正确使用字段对象)。
Dim fMinLongitude As ADODB.Field
Dim fMinLatitude As ADODB.Field
Dim fMaxLongitude As ADODB.Field
Dim fMaxLatitude As ADODB.Field
Dim fStreetCount As ADODB.Field
If RS.RecordCount = 0 Then
Exit Sub
End If
Set fMinLongitude = RS.Fields.Item("MinLongitude")
Set fMinLatitude = RS.Fields.Item("MinLatitude")
Set fMaxLongitude = RS.Fields.Item("MaxLongitude")
Set fMaxLatitude = RS.Fields.Item("MaxLatitude")
Set fStreetCount = RS.Fields.Item("StreetCount")
While Not RS.EOF
LineGridCount = LineGridCount + 1
With LineGrid(LineGridCount)
.MinLongitude = fMinLongitude.Value
.MaxLongitude = fMaxLongitude.Value
.MinLatitude = fMinLatitude.Value
.MaxLatitude = fMaxLatitude.Value
End With
RS.MoveNext
Wend
RS.Close
Set RS = Nothing
请注意,我为 SQL Server 存储过程返回的 5 列设置了字段对象。然后我在一个循环中使用它们。当您执行 RS.MoveNext 时,它会影响字段对象。
使用上面显示的代码,我可以在不到 1 秒的时间内将 26,000 行加载到我的用户定义类型中。事实上,运行代码只需要 0.05 秒。在已编译的应用程序中,它甚至更快。
如果你不使用字段对象,那么你至少应该使用 WITH 块。如另一篇文章所述,使用序数位置比其他替代方法更快(字段方法除外)。如果您打算使用序数位置,那么您应该使用 WITH 块。例如:
With RS.Fields
ID = .Item(0).Value
Name = .Item(1).Value
EyeColor = .Item(2).Value
End With
使用 with 块很好,因为它减少了输入量,同时加快了代码的执行速度。之所以会出现这种性能提升,是因为 VB 可以设置一次指向字段对象的指针,然后在每次调用字段对象时重用该指针。
顺便说一句...我不喜欢“少打字”的说法。我经常发现性能更好的代码也是更复杂的代码。使用 VB6 的智能感知,额外的输入也不是那么多。
RS("FieldName") 为 15 个字符。
我已经养成了打字的习惯: rs (dot) f (dot) i (open parenthesis) (quote) FieldName (quote) (Close Parenthesis) (dot) v. 这是使用完全合格的方法。
使用with block方法,就是(点)i(开括号)(引号)FieldName(引号)(右括号)(点)v,也就是17次按键。
在这种情况下,一个好习惯只需付出很少的努力,就能通过更好的代码获得巨大的回报。
我刚刚做了一些性能测试。以下测试使用客户端游标,这意味着查询返回的所有数据都被复制到客户端计算机并存储在记录集对象中。
我用于性能测试的代码是这样的:
Private Sub Command1_Click()
Dim DB As ADODB.Connection
Dim RS As ADODB.Recordset
Dim Results() As String
Set DB = New ADODB.Connection
DB.ConnectionString = "my connection string here"
DB.CursorLocation = adUseClient
DB.Open
Set RS = New ADODB.Recordset
Call RS.Open("Select * From MapStreetsPoints", DB, adOpenForwardOnly, adLockReadOnly)
Dim Start As Single
Dim FeatureId As Long
Dim PointNumber As Long
Dim Longitude As Single
Dim Latitude As Single
Dim fFeatureId As ADODB.Field
Dim fPointNumber As ADODB.Field
Dim fLongitude As ADODB.Field
Dim fLatitude As ADODB.Field
ReDim Results(5)
RS.MoveFirst
Start = Timer
Do While Not RS.EOF
FeatureId = RS!FeatureId
PointNumber = RS!PointNumber
Longitude = RS!Longitude
Latitude = RS!Latitude
RS.MoveNext
Loop
Results(0) = "Bang Method: " & Format(Timer - Start, "0.000")
RS.MoveFirst
Start = Timer
Do While Not RS.EOF
FeatureId = RS.Fields.Item("FeatureId").Value
PointNumber = RS.Fields.Item("PointNumber").Value
Longitude = RS.Fields.Item("Longitude").Value
Latitude = RS.Fields.Item("Latitude").Value
RS.MoveNext
Loop
Results(1) = "Fully Qualified Name Method: " & Format(Timer - Start, "0.000")
RS.MoveFirst
Start = Timer
Do While Not RS.EOF
FeatureId = RS.Fields.Item(0).Value
PointNumber = RS.Fields.Item(1).Value
Longitude = RS.Fields.Item(2).Value
Latitude = RS.Fields.Item(3).Value
RS.MoveNext
Loop
Results(2) = "Fully Qualified Ordinal Method: " & Format(Timer - Start, "0.000")
RS.MoveFirst
Start = Timer
With RS.Fields
Do While Not RS.EOF
FeatureId = .Item("FeatureId").Value
PointNumber = .Item("PointNumber").Value
Longitude = .Item("Longitude").Value
Latitude = .Item("Latitude").Value
RS.MoveNext
Loop
End With
Results(3) = "With Block Method: " & Format(Timer - Start, "0.000")
RS.MoveFirst
Start = Timer
With RS.Fields
Do While Not RS.EOF
FeatureId = .Item(0).Value
PointNumber = .Item(1).Value
Longitude = .Item(2).Value
Latitude = .Item(3).Value
RS.MoveNext
Loop
End With
Results(4) = "With Block Ordinal Method: " & Format(Timer - Start, "0.000")
RS.MoveFirst
Start = Timer
Set fFeatureId = RS.Fields.Item("FeatureId")
Set fPointNumber = RS.Fields.Item("PointNumber")
Set fLatitude = RS.Fields.Item("Latitude")
Set fLongitude = RS.Fields.Item("Longitude")
Do While Not RS.EOF
FeatureId = fFeatureId.Value
PointNumber = fPointNumber.Value
Longitude = fLongitude.Value
Latitude = fLatitude.Value
RS.MoveNext
Loop
Results(5) = "Field Method: " & Format(Timer - Start, "0.000")
Text1.Text = "Rows = " & RS.RecordCount & vbCrLf & Join(Results, vbCrLf)
End Sub
结果是:
Rows = 2,775,548
Bang Method: 9.441
Fully Qualified Name Method: 9.367
Fully Qualified Ordinal Method: 5.191
With Block Method: 8.527
With Block Ordinal Method: 5.117
Field Method: 4.316
显然,现场方法是赢家。所需时间不到 bang 方法的 1/2。另请注意,与字段方法相比,序数方法也具有不错的性能。