views:

178

answers:

2

I am writing a stored procedure that when completed will be used to scan staging tables for bogus data on a column by column basis.

Step one in the exercise was just to scan the table --- which is what the code below does. The issue is that this code runs in 5:45 seconds --- however the same code run as a console app (changing the connectionstring of course) runs in about 44 seconds.

    using (SqlConnection sqlConnection = new SqlConnection("context connection=true"))
    {
        sqlConnection.Open();
        string sqlText = string.Format("select * from {0}", source_table.Value);
        int count = 0;
        using (SqlCommand sqlCommand = new SqlCommand(sqlText, sqlConnection))
        {
            SqlDataReader reader = sqlCommand.ExecuteReader();
            while (reader.Read())
                count++;
            SqlDataRecord record = new SqlDataRecord(new SqlMetaData("rowcount", SqlDbType.Int));
            SqlContext.Pipe.SendResultsStart(record);
            record.SetInt32(0, count);
            SqlContext.Pipe.SendResultsRow(record);
            SqlContext.Pipe.SendResultsEnd();
        }
    }

However the same code (different connection string of course) runs in a console app in about 44 seconds (which is closer to what I was expecting on the client side)

What am I missing on the SP side, that would cause it to run so slow.

Please note: I fully understand that if I wanted a count of rows, I should use the count(*) aggregation --- that's not the purpose of this exercise.

+1  A: 

Well it would seem the answer is in the connection string after all.

context connection=true

versus

server=(local); database=foo; integrated security=true

For some bizzare reason, using the "external" connection the SP runs almost as fast as a console app (still not as fast mind you! -- 55 seconds)

Of course now the assembly has to be deployed as External rather than Safe --- and that introduces more frustration.

Ralph Shillington
+2  A: 

The type of code you are writing is highly susceptible to SQL Injection. Rather than processing the reader like you are, you could just use the RecordsAffected Property to find the number of rows in the reader.

EDIT:

After doing some research, the difference you are seeing is a by design difference between the context connection and a regular connection. Peter Debetta blogged about this and writes:

"The context connection is written such that it only fetches a row at a time, so for each of the 20 million some odd rows, the code was asking for each row individually. Using a non-context connection, however, it requests 8K worth of rows at a time."

http://sqlblog.com/blogs/peter_debetta/archive/2006/07/21/context-connection-is-slow.aspx

Jonathan Kehayias
The question was not about sql injection hacks, nor getting the count of rows --- it was about performance of the SqlDataReader, which is why I included the original disclaimer.
Ralph Shillington
After doing some research, the difference you are seeing is a by design difference between the context connection and a regular connection. Peter Debetta blogged about this and writes:"The context connection is written such that it only fetches a row at a time, so for each of the 20 million some odd rows, the code was asking for each row individually. Using a non-context connection, however, it requests 8K worth of rows at a time."http://sqlblog.com/blogs/peter_debetta/archive/2006/07/21/context-connection-is-slow.aspx
Jonathan Kehayias