Results 1 to 14 of 14

Thread: Speed up this very short piece of SQL?

  1. #1

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359

    Speed up this very short piece of SQL?

    I have the following code in an XML Web Service, and need to speed it up a bit. It takes about half a second to complete, and its called about 17000 times in a row. Any thoughts?

    VB Code:
    1. <WebMethod()> Public Function UpdateProductInLocalDB(ByVal strDetails As String) As Boolean
    2.         Try            
    3.             Dim strTemp() As String = Split(strDetails, vbLf)
    4.             Dim strSQLStatement As String, mySqlConnection As SqlConnection
    5.             If strTemp.GetUpperBound(0) = 12 Then
    6.                 Dim strProductDetails = "'" & strTemp(0) & "', " & "'" & strTemp(1) & "', " & "'" & strTemp(2) & "', "
    7.                 strProductDetails &= "'" & strTemp(3) & "', " & "'" & strTemp(4) & "', " & "'" & strTemp(5) & "', "
    8.                 strProductDetails &= "'" & strTemp(6) & "', " & strTemp(7) & ", " & "'" & strTemp(8) & "', "
    9.                 strProductDetails &= "'" & strTemp(9) & "', " & "'" & strTemp(10) & "', " & "'" & strTemp(11) & "'"
    10.                 strSQLStatement = "DELETE FROM tblProducts WHERE strProductReference = '" & strTemp(0) & "';"
    11.                 strSQLStatement &= "INSERT INTO tblProducts VALUES (" & strProductDetails & ");"
    12.                 mySqlConnection = New SqlConnection(strConnectionString) : mySqlConnection.Open()
    13.                 Dim mySQLCommand As New SqlCommand(strSQLStatement, mySqlConnection)
    14.                 mySQLCommand.ExecuteNonQuery() : mySqlConnection.Close() : mySqlConnection = Nothing
    15.                 Return True
    16.             Else
    17.                 Throw New Exception("strTemp.GetUpperBound(0) != 12")
    18.             End If
    19.         Catch ex As Exception
    20.             ErrorLog(Now & vbCrLf & ex.ToString & vbCrLf & vbCrLf & strDetails & vbCrLf & vbCrLf & strConnectionString & vbCrLf & vbCrLf)
    21.             Return False
    22.         End Try
    23.     End Function
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  2. #2
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687
    What about moving the ExecuteNoQuery out of the loop, and create two SQL strings, one with the Delete in it - using "WHERE strProductReference IN (...)" and one with all of the INSERTS in it. Then execute the DELETE SQL, then the INSERT.

    Although, I wonder why you are deleting and inserting when a simple update looks like it would suffice.

    TG
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  3. #3

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Because there is a possibility a product may not yet exist inside the DB. I've modified the code a bit, dumping the entire contents of the table first, and then passing the details to an SP.
    I'll post the code in a sec...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  4. #4

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    VB Code:
    1. <WebMethod()> Public Sub UpdateProductInLocalDB(ByVal strDetails As String)
    2.         Try
    3.             Dim strSQLStatement As String, mySqlConnection As SqlConnection
    4.             Dim mySQLCommand As SqlCommand
    5.             If Not blnCleared(0) Then
    6.                 blnCleared(0) = True
    7.                 strSQLStatement = "DELETE FROM tblProducts"
    8.                 mySqlConnection = New SqlConnection(strConnectionString) : mySqlConnection.Open()
    9.                 mySQLCommand = New SqlCommand(strSQLStatement, mySqlConnection)
    10.                 mySQLCommand.ExecuteNonQuery() : mySqlConnection.Close() : mySqlConnection = Nothing
    11.                 UpdateProductInLocalDB(strDetails)
    12.             Else
    13.                 Dim strTemp() As String = Split(strDetails, vbLf)
    14.                 Dim strProductDetails = "'" & strTemp(0) & "', " & "'" & strTemp(1) & "', " & "'" & strTemp(2) & "', "
    15.                 strProductDetails &= "'" & strTemp(3) & "', " & "'" & strTemp(4) & "', " & "'" & strTemp(5) & "', "
    16.                 strProductDetails &= "'" & strTemp(6) & "', " & strTemp(7) & ", " & "'" & strTemp(8) & "', "
    17.                 strProductDetails &= "'" & strTemp(9) & "', " & "'" & strTemp(10) & "', " & "'" & strTemp(11) & "'"                
    18.                 strSQLStatement = "{CALL SQLAddProductToDB(" & strProductDetails & ")}"
    19.                 mySqlConnection = New SqlConnection(strConnectionString) : mySqlConnection.Open()
    20.                 mySQLCommand = New SqlCommand(strSQLStatement, mySqlConnection)
    21.                 mySQLCommand.ExecuteNonQuery() : mySqlConnection.Close() : mySqlConnection = Nothing
    22.             End If
    23.         Catch ex As Exception
    24.             ErrorLog(Now & vbCrLf & ex.ToString & vbCrLf & vbCrLf & strDetails & vbCrLf & vbCrLf & strConnectionString & vbCrLf & vbCrLf)
    25.         End Try
    26.     End Sub

    And the SP:
    Code:
    CREATE PROCEDURE SQLAddProductToDB 
    	@param0 varchar(50), @param1 varchar(512), 
    	@param2 varchar(512), @param3 varchar(512), 
    	@param4 varchar(512), @param5 varchar(512), 
    	@param6 varchar(512), @param7 int, 
    	@param8 varchar(512), @param9 varchar(512), 
    	@param10 varchar(512), @param11 varchar(512)
    AS
    	INSERT INTO tblProducts VALUES (@param0, @param1, @param2, @param3, @param4, @param5, @param6, @param7, @param8, @param9, @param10, @param11);
    GO
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  5. #5
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687
    What DBMS are you using? If you are doing a stored procedure, it would be more efficient to do
    Code:
    IF EXISTS (SELECT * FROM tblProducts  WHERE strProductReference = @IDParam)
      BEGIN
        UPDATE tblPRoducts 
         SET ......
    
      END
    ELSE
      BEGIN
        INSERT INTO tblProducts
          (Fields...)
        VALUES
          (Parameters...)
      END
    That's how we do it here. Updates if the record is there, inserts it if not.

    TG

    EDIT: I see now, it looks like you are using MySQL, no? Not sure if it supports the EXISTS keyword. Even still, you could do a Count..... no, wait.... grrr....... Let me think this over.....
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  6. #6

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Using MS SQL 2000. The reason I don't want to check if the record exists first, is that, well, why bother?
    If the record does exist, we've just performed a search, and then will have to update it - i.e. another search and modification.
    If the record does not exist, we've just performed a search, and then we have to insert a new record.

    Surely better to just delete the record if its there, and then insert...?
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  7. #7

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Okay now this takes 2.5 seconds per 1% of the products listing, which is 17000 products, which equates to 170 products per 2.5 seconds which equates to on average 68 products per second inserted into the DB.

    VB.NET Application to Insert Data:
    VB Code:
    1. Public Sub sqlAddProductToDB(ByVal product As clsProduct)
    2.         If blnHaveCleared(0) Then
    3.             Dim strSQLStatement As String = "DELETE FROM tblProducts"
    4.             Dim sqlCommand As New SqlCommand(strSQLStatement, New SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=dbShop;Data Source=JAMIE02;Packet Size=4096;Workstation ID=JAMIE02;"))
    5.             sqlCommand.ExecuteNonQuery() : sqlCommand = Nothing
    6.             blnHaveCleared(0) = True
    7.         End If
    8.         [b]myUpdateService.UpdateProductInLocalDB(product.ToString())[/b]
    9.     End Sub

    myUpdateService.UpdateProductInLocalDB is a web reference to an XML Web Service running locally. This is the UpdateProductInLocalDB() method:

    VB Code:
    1. <WebMethod()> Public Sub UpdateProductInLocalDB(ByVal strDetails As String)
    2.         Try
    3.             Dim strSQLStatement As String, mySqlConnection As SqlConnection
    4.             Dim mySQLCommand As SqlCommand            
    5.             Dim strTemp() As String = Split(strDetails, vbLf)
    6.             Dim strProductDetails = "'" & strTemp(0) & "', " & "'" & strTemp(1) & "', " & "'" & strTemp(2) & "', "
    7.             strProductDetails &= "'" & strTemp(3) & "', " & "'" & strTemp(4) & "', " & "'" & strTemp(5) & "', "
    8.             strProductDetails &= "'" & strTemp(6) & "', " & strTemp(7) & ", " & "'" & strTemp(8) & "', "
    9.             strProductDetails &= "'" & strTemp(9) & "', " & "'" & strTemp(10) & "', " & "'" & strTemp(11) & "'"
    10.             [b]strSQLStatement = "EXECUTE SQLAddProductToDB " & strProductDetails & ""[/b]
    11.             mySqlConnection = New SqlConnection(strConnectionString) : mySqlConnection.Open()
    12.             mySQLCommand = New SqlCommand(strSQLStatement, mySqlConnection)
    13.             mySQLCommand.ExecuteNonQuery() : mySqlConnection.Close() : mySqlConnection = Nothing
    14.         Catch ex As Exception
    15.             ErrorLog(Now & vbCrLf & ex.ToString & vbCrLf & vbCrLf & strDetails & vbCrLf & vbCrLf & strConnectionString & vbCrLf & vbCrLf)
    16.         End Try
    17.     End Sub

    The SQLAddProductToDB SP is stored in the MS SQL 2000 Server running locally, and is defined as follows:

    Code:
    CREATE PROCEDURE SQLAddProductToDB 
    	@param0 varchar(50), @param1 varchar(512), 
    	@param2 varchar(512), @param3 varchar(512), 
    	@param4 varchar(512), @param5 varchar(512), 
    	@param6 varchar(512), @param7 int, 
    	@param8 varchar(512), @param9 varchar(512), 
    	@param10 varchar(512), @param11 varchar(512)
    AS
    	INSERT INTO tblProducts VALUES (@param0, @param1, @param2, @param3, @param4, @param5, @param6, @param7, @param8, @param9, @param10, @param11);
    GO
    Ahhh
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  8. #8
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687
    Originally posted by plenderj
    Using MS SQL 2000. The reason I don't want to check if the record exists first, is that, well, why bother?
    If the record does exist, we've just performed a search, and then will have to update it - i.e. another search and modification.
    If the record does not exist, we've just performed a search, and then we have to insert a new record.

    Surely better to just delete the record if its there, and then insert...?
    That's the beauty of the EXISTS, it actualy doesn't do a search, it checks the index tables (you DO have an index on the table, right?) and it is faster, because no data is actualy returned, it's not a full lookup. Besides the DELETE is a look up too. It's got to check to see if the record is there to be deleted. 6 of one half-dozen of another. It's been my experience that using EXISTS is faster than looking for the record. I know I've seen an article somewhere regarding the efficientcies of SELECT COUNT (*) vs IF EXISTS when determining if a record is there.

    And if you do have indexes on the table, the DELETE/INSERT combo is going to degrade performance since it will need to update statistics after each call.

    TG
    Just my $0.02 worth
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  9. #9

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Hmmmmmm an Index table you say... I'll have to investigate this...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  10. #10
    PowerPoster hellswraith's Avatar
    Join Date
    Jul 2002
    Location
    Washington St.
    Posts
    2,464
    It isn't the statement, it is the web service call itself that is taking a while.

    What you should do instead is pass in an array of details (1700 of them) to the web service, and loop through them in the service. MUCHO faster. Do a timer, you will see.

    May not be completely accurate, but you get my point:
    VB Code:
    1. <WebMethod()> Public Function UpdateProductInLocalDB(ByVal strDetails() As String) As Boolean
    2.         Try            
    3.             For Each strDetail As String In strDetails
    4.             Dim strTemp() As String = Split(strDetail, vbLf)
    5.             Dim strSQLStatement As String, mySqlConnection As SqlConnection
    6.             If strTemp.GetUpperBound(0) = 12 Then
    7.                 Dim strProductDetails = "'" & strTemp(0) & "', " & "'" & strTemp(1) & "', " & "'" & strTemp(2) & "', "
    8.                 strProductDetails &= "'" & strTemp(3) & "', " & "'" & strTemp(4) & "', " & "'" & strTemp(5) & "', "
    9.                 strProductDetails &= "'" & strTemp(6) & "', " & strTemp(7) & ", " & "'" & strTemp(8) & "', "
    10.                 strProductDetails &= "'" & strTemp(9) & "', " & "'" & strTemp(10) & "', " & "'" & strTemp(11) & "'"
    11.                 strSQLStatement = "DELETE FROM tblProducts WHERE strProductReference = '" & strTemp(0) & "';"
    12.                 strSQLStatement &= "INSERT INTO tblProducts VALUES (" & strProductDetails & ");"
    13.                 mySqlConnection = New SqlConnection(strConnectionString) : mySqlConnection.Open()
    14.                 Dim mySQLCommand As New SqlCommand(strSQLStatement, mySqlConnection)
    15.                 mySQLCommand.ExecuteNonQuery() : mySqlConnection.Close() : mySqlConnection = Nothing
    16.                
    17.             Else
    18.                 Throw New Exception("strTemp.GetUpperBound(0) != 12")
    19.             End If
    20.             Loop
    21.             Return True
    22.         Catch ex As Exception
    23.             ErrorLog(Now & vbCrLf & ex.ToString & vbCrLf & vbCrLf & strDetails & vbCrLf & vbCrLf & strConnectionString & vbCrLf & vbCrLf)
    24.             Return False
    25.         End Try
    26.     End Function

  11. #11

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Yeah I'd already thought of that and I'll be putting that in
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  12. #12
    I wonder how many charact
    Join Date
    Feb 2001
    Location
    Savage, MN, USA
    Posts
    3,704
    Well, after techgnome's and hells suggestion.... which was killer... the only remaining suggestion would probably gain you 1/10th a second, if that...


    VB Code:
    1. Dim strProductDetails = "'" & strTemp(0) & "', " & "'" & strTemp(1) & "', " & "'" & strTemp(2) & "', "
    2.                 strProductDetails &= "'" & strTemp(3) & "', " & "'" & strTemp(4) & "', " & "'" & strTemp(5) & "', "
    3.                 strProductDetails &= "'" & strTemp(6) & "', " & strTemp(7) & ", " & "'" & strTemp(8) & "', "
    4.                 strProductDetails &= "'" & strTemp(9) & "', " & "'" & strTemp(10) & "', " & "'" & strTemp(11) & "'"
    5.                 strSQLStatement = "DELETE FROM tblProducts WHERE strProductReference = '" & strTemp(0) & "';"
    6.                 strSQLStatement &= "INSERT INTO tblProducts VALUES (" & strProductDetails & ");"
    That's a heck of a lot of string to throw together....

    Stringbuilder or string.concat would make me feel more comfortable and warm and fuzzy inside.....

  13. #13

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Ahhhh. Nice one thanks
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  14. #14
    Member
    Join Date
    Sep 2004
    Location
    Oklahoma City, OK
    Posts
    36
    I'll offer that to improve your overall code performance, try this approach instead of the string concatenation:

    VB Code:
    1. <WebMethod()> Public Sub UpdateProductInLocalDB(ByVal strDetails As String)
    2.     Dim myConnection As SqlConnection = New SqlConnection(strConnectionString)
    3.     Dim myCommand As SqlCommand
    4.     Try
    5.         If Not blnCleared(0) Then
    6.             blnCleared(0) = True
    7.             myCommand = new SqlCommand("DELETE FROM tblProducts", myConnection)
    8.             myCommand.Connection.Open()
    9.             myCommand.ExecuteNonQuery()
    10.             UpdateProductInLocalDB(strDetails)
    11.         Else
    12.             Dim strTemp() As String = Split(strDetails, vbLf)
    13.             myCommand = new SqlCommand("SqlAddProductToDB", myConnection)
    14.             myCommand.CommandType = CommandType.StoredProcedure
    15.            
    16.             myCommand.Parameters.Add("@param0", SqlDbType.VarChar, 50).Value = strTemp(0)
    17.             myCommand.Parameters.Add("@param1", SqlDbType.VarChar, 512).Value = strTemp(1)
    18.             myCommand.Parameters.Add("@param2", SqlDbType.VarChar, 512).Value = strTemp(2)
    19.             myCommand.Parameters.Add("@param3", SqlDbType.VarChar, 512).Value = strTemp(3)
    20.             myCommand.Parameters.Add("@param4", SqlDbType.VarChar, 512).Value = strTemp(4)
    21.             myCommand.Parameters.Add("@param5", SqlDbType.VarChar, 512).Value = strTemp(5)
    22.             myCommand.Parameters.Add("@param6", SqlDbType.VarChar, 512).Value = strTemp(6)
    23.             myCommand.Parameters.Add("@param7", SqlDbType.Int).Value = CType(strTemp(7), Integer)
    24.             myCommand.Parameters.Add("@param8", SqlDbType.VarChar, 512).Value = strTemp(8)
    25.             myCommand.Parameters.Add("@param9", SqlDbType.VarChar, 512).Value = strTemp(9)
    26.             myCommand.Parameters.Add("@param10", SqlDbType.VarChar, 512).Value = strTemp(10)
    27.             myCommand.Parameters.Add("@param11", SqlDbType.VarChar, 512).Value = strTemp(11)
    28.            
    29.             myCommand.Connection.Open()
    30.             myCommand.ExecuteNonQuery()
    31.         End If
    32.     Catch ex As Exception
    33.         ErrorLog(Now & vbCrLf & ex.ToString & vbCrLf & vbCrLf & strDetails & vbCrLf & vbCrLf & strConnectionString & vbCrLf & vbCrLf)
    34.     Finally
    35.         myConnection.Close()
    36.         myConnection.Dispose()
    37.         myConnection = Nothing
    38.     End Try
    39. End Sub

    This will result in one connection object being handled throughout the procedure, and the parameterized version of the SqlCommand object will enable type casting/checking to insure conformity with the Stored Procedure.
    Thomas Corey
    IT Engineering Consultant
    TALSoft Enterprises Inc.
    Oklahoma City, OK

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width