Re: SqlDataAdapter.Update()

From: Mike Labosh (mlabosh_at_hotmail.com)
Date: 10/07/04


Date: Thu, 7 Oct 2004 17:25:05 -0400


> However, I don't think you're approaching this problem in the most
> efficient manner. Even building a bunch of UPDATE statements is going to
> be pretty slow compared to executing an intelligent UPDATE on the server.
> The only question I have is where do the new @Quantity values come from?

Well since I'm working on a real system and not Northwind, there are no
quantity values :)

> If you write server-side UPDATE that performed this logic it would run an
> order of magnitude faster as the data would not have to be transported to
> the client, changed and sent back--it could be changed in place.

I agree. I could do this as a stored procedure, but this giant
string-chewing algorithm wouldn't work well in SQL. There is a lot of
looping over words in the string and parsing them off, which in SQL would
likely need evil cursors. There is also 5 or 6 rather bizarre regular
expressions used, and in SQL, that would mean using the sp_OA* procs to use
the Scripting.RegExp object.

> One approach might be to bulk copy the changes to the server with the PK
> and the delta value into a temporary table and do the smart UPDATE joining
> against that table. There are other ways as well...

I actually thought of designing it that way, but there's not really a
"delta". Each value is updated differently based on its content. It
wouldn't be like marking up a price column by n% or like Trimming.

Maybe tonight I'll try a thread-based solution, where one thread can read
from a DataReader, marshal it to another thread that does the big fat
algorithm, and marshal the result to another thread that passes it to a
stored procedure. Maybethey could share a pair of synchronized Queue
objects. Of course, now that I just read what my hands typed on autopilot,
this thread idea probably means it's time to knock off for the day.

-- 
Peace & happy computing,
Mike Labosh, MCSD
"It's 4:30 am.  Do you know where your stack pointer is?"
"William (Bill) Vaughn" <billvaRemoveThis@nwlink.com> wrote in message 
news:%23dWNuELrEHA.1988@TK2MSFTNGP09.phx.gbl...
>
> hth
>
> -- 
> ____________________________________
> William (Bill) Vaughn
> Author, Mentor, Consultant
> Microsoft MVP
> www.betav.com
> Please reply only to the newsgroup so that others can benefit.
> This posting is provided "AS IS" with no warranties, and confers no 
> rights.
> __________________________________
>
> "Mike Labosh" <mlabosh@hotmail.com> wrote in message 
> news:%23sFhX6KrEHA.3868@TK2MSFTNGP15.phx.gbl...
>> I'm not asking a question here, I'm sharing some insight I just 
>> discovered. Consider the following [air] code.  My actual code operates 
>> on a huge table with over a million and a half records, so I have to loop 
>> in blocks of 100,000 at a time, and the "processing" that it does to the 
>> data is several pages long, not a silly += 1 that I did in this post.
>>
>> Dim cnstr As String = "connect to SQL Northwind"
>> Dim cn As New SqlConnection(cnstr)
>> Dim da As New SqlDataAdapter()
>> Dim dt As New DataTable()
>> Dim sel As String = "SELECT * FROM [Order Details]"
>> Dim upd As String = _
>>    "UPDATE [Order Details] SET Quantity = @quantity " & _
>>    "WHERE OrderID = @orderID AND ProductID = @productID"
>>
>> With da    'Setup a data adapter to select and update
>>    .SelectCommand = New SqlCommand(sel, cn)
>>    .UpdateCommand = New SqlCommand(upd, cn)
>>
>>    With .UpdateCommand.Parameters
>>        .Add("@quantity", SqlDbType.Int)
>>        .Add("@orderID", SqlDbType.Int)
>>        .Add("@productID", SqlDbType.Int)
>>    End With
>>
>>    .Fill(dt)    'Get some rows
>>
>>    'Do some kind of processing
>>    For Each dr As DataRow In dt.Rows
>>        'I know this is the dumb way to update, but this
>>        'isn't what I'm getting at.
>>        dr("Quantity") = CType(dr("Quantity"), Integer) + 1
>>    Next
>>
>>    'Update them.
>>    .Update(dt)
>>
>> End With
>>
>> Now, all the microsoft documentation I have ever read about the data 
>> adapter vaguely implies that it is really really fast, and I have always 
>> understood that the data adapter did something like this inside the 
>> update method to gain performance through fewer round trips to the 
>> server:
>>
>> Dim bigFatCommand as String
>>
>> For i = 0 to CountOfChanges
>>    bigFatCommand &= vbCrLf & "update table set fld = 'asdf'...;"
>> Next i
>>
>> cn.Open()
>> sqlCmd.CommandText = bigFatCommand
>> sqlCmd.ExecuteNonQuery
>> cn.Close()
>>
>> What I have discovered today is that's not how it works at all.  You can 
>> verify this with the SQL Profilier.  Startup a session in the profiler 
>> and have it watch for RPC:Completed events.  Then run code similar to 
>> that at the top of this post.  When you run the VB in the debugger, you 
>> can pause the debugger and all activity with SQL Server in the Profiler 
>> stops. Unpause it, and there is activity again.  Pause it and the 
>> activity stops. This demonstrates that the Data Adapter is actually 
>> sending one command for each individual updated record, like this:
>>
>> cn.Open()
>>
>> For i = 0 to CountOfChanges
>>    sqlCmd.CommandText = "update table set fld = ..."
>>    sqlCmd.ExecuteNonQuery()
>> Next i
>>
>> cn.Close()
>>
>> Note that the Profiler demonstrates that the data adapter is not opening 
>> and closing the connection inside the loop, but DANG it sure makes a lot 
>> of calls across the network!
>>
>> In conclusion, I have decided that gigantor batch processing needs a more 
>> clever solution than the DataAdapter.  I am going to use a StringBuilder 
>> to build huge stacks of commands, and send just one big fat string of 
>> updates in a single round trip.
>> -- 
>> Peace & happy computing,
>>
>> Mike Labosh, MCSD
>>
>> "It's 4:30 am.  Do you know where your stack pointer is?"
>>
>
> 


Relevant Pages

  • Re: multiplatform (pocketPC & desktopPC) (Daniel !!)
    ... Friend Versione As String ... Public Sub GetMyConnectionPalmare() ... Dim errorMessages As String ... Private Function GetDS_Desktop(ByVal SQL As String) As DataSet ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: multiplatform (pocketPC & desktopPC) (Daniel !!)
    ... Friend Versione As String ... Public Sub GetMyConnectionPalmare() ... Dim errorMessages As String ... Private Function GetDS_Desktop(ByVal SQL As String) As DataSet ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: Performance von SQL-Abfragen auf Exceltabellen
    ... Nun habe ich es mit SQL auf Exceldaten versucht und konnte das ganze ... Performance konstant bei rund 3 Sekunden. ... Dim iColumnCount As Long ... Dim FirstColumnforSQLexists_jn As String 'j if first column for SQL ...
    (microsoft.public.de.excel)
  • Re: search by 1 of 3 combos
    ... I guess I should expand a bit on an example of what you can do with modifying SQL for a search combo... ... , mWhere as string ... Dim mRecordID As Long ... Private Sub cmd_search_Click ...
    (microsoft.public.access.formscoding)
  • SqlDataAdapter.Update()
    ... Dim cnstr As String = "connect to SQL Northwind" ... Dim cn As New SqlConnection ... all the microsoft documentation I have ever read about the data adapter ... the debugger and all activity with SQL Server in the Profiler stops. ...
    (microsoft.public.dotnet.framework.adonet)

Loading