Link to home
Start Free TrialLog in
Avatar of Brian
BrianFlag for United States of America

asked on

Code Performance

Hello,

Is there any way that i can make the following code and stored procedure run faster by modifying it or does it look okay?

Stored Procedure:
ALTER  PROCEDURE [dbo].[PSSA_GradeReport]

@grd_id int

As

select s.student_id, s.firstname, s.lastname, s.dob, s.gender, s.ethnicity, s.phone, s.entrydate, s.pasecureid, s.spedaccnotes, s.teacher, s.loginuser, s.lastupdated, dbo.StudentTests(s.student_id) testname, s.grd_id, g.grd_id, g.grd_level, i.iep_id, i.iep_type
From pssa_students as s
Join pssa_grades as g On s.grd_id = g.grd_id
Join pssa_iep as i On s.iep_id = i.iep_id
where g.grd_id = @grd_id

CODE:
Protected Sub GradesReport(ByVal s As Object, ByVal e As EventArgs) Handles Me.Load

        Dim connectionString As String = ConfigurationManager.ConnectionStrings("PSSA").ConnectionString
        Dim conn As SqlConnection = New SqlConnection(connectionString)

        ' Create Querystring
        Dim grd_id As Int32 = Request.QueryString("@grd_id")

        Dim greportComm As SqlCommand

        greportComm = New SqlCommand("PSSA_GradeReport", conn)
        greportComm.CommandType = CommandType.StoredProcedure

        ' Create Parameter for Querystring
        greportComm.Parameters.Add("@grd_id", SqlDbType.VarChar)
        greportComm.Parameters("@grd_id").Value = Request("grd_id")

        Try
            conn.Open()

            Dim dr As SqlDataReader = greportComm.ExecuteReader()

            greportList.DataSource = dr
            greportList.DataBind()

        Catch ex As Exception

        Finally
            conn.Close()
        End Try

    End Sub
Avatar of Avodah
Avodah
Flag of United Kingdom of Great Britain and Northern Ireland image

Everything you have shown here for the most part looks fine. With regards to the the stored procedure you might want to try various indexes and check the performance. You will want to put indexes included a clustered index on the grades tables (I recommend clustered because I assume this table is fairly small and does not change much). Place the clustered index on the grd_id column. I am not sure what the pssa_iep table contains but you may want to look into the same thing if it meets the criteria.

You can also try adding the NOLOCK hint to the select statement for more scalability.

select s.student_id, s.firstname, s.lastname, s.dob, s.gender, s.ethnicity, s.phone, s.entrydate, s.pasecureid, s.spedaccnotes, s.teacher, s.loginuser, s.lastupdated, dbo.StudentTests(s.student_id) testname, s.grd_id, g.grd_id, g.grd_level, i.iep_id, i.iep_type
From pssa_students as s (Nolock)
Join pssa_grades as g On s.grd_id = g.grd_id
Join pssa_iep as i On s.iep_id = i.iep_id
where g.grd_id = @grd_id


In your VB code since you do not do anything in the CATCH block you might simply want to use the USING keyword to open the connection and remove the exception handling code.

using conn As New SqlConnection(connectionString)
            conn.Open()

            Dim dr As SqlDataReader = greportComm.ExecuteReader()

            greportList.DataSource = dr
            greportList.DataBind()
End Using

You will need to rearrange your code to use this construct this way.
Avatar of Brian

ASKER

DaTribe,

Ok, a couple questions i have.

What does NOLOCK do? How do i place a clustered index on a PK within my tables? Also most importantly i have seen examples of the using block but don't fully understand the differece from the way i have it now. If it's a performance boost then i will switch to it. Can you help me with that by changing with what i have now?

Thanks in advance!!!!
OK here goes:

1. NOLOCK is a hint to SQL server asking it if its possible not to lock the table and allow other queries to access it. Therefore more queries can run simultaneously.

http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1170220,00.html#block

The rest of the article has performance tips

2. Follow the instructions in this link to add a clustered index:

http://msdn.microsoft.com/en-us/library/ms188245.aspx

3. The try catch block has an overhead therefore the more you can avoid it the better. It is probably a much better option to put the block within your business logic rather than your data access layer, leaving your data access layer to run as fast as possible.

The USING keyword provides a way to create an object - a class that implements the IDisposable interface -, in this case the SqlConnection and performs a dispose of the object at the end of the block. Therefore no matter how that using block is exited the SqlConnection will be disposed of (eliminating the finally block) and the connection will be closed.


Protected Sub GradesReport(ByVal s As Object, ByVal e As EventArgs) Handles Me.Load
 
    ' Get database connection string
    Dim connectionString As String = ConfigurationManager.ConnectionStrings("PSSA").ConnectionString
 
    ' Create Querystring
    Dim grd_id As Int32 = Request.QueryString("@grd_id")
 
    Using conn As New SqlConnection(connectionString)
 
        Dim greportComm As New SqlCommand("PSSA_GradeReport", conn)
        greportComm.CommandType = CommandType.StoredProcedure
 
        ' Create Parameter for Querystring
        greportComm.Parameters.Add("@grd_id", SqlDbType.VarChar)
        greportComm.Parameters("@grd_id").Value = Request("grd_id")
 
        conn.Open()
        greportList.DataSource = greportComm.ExecuteReader()
        greportList.DataBind()
 
    End Using
 
End Sub

Open in new window

Avatar of Brian

ASKER

DaTribe,

Thanks for the info! Just a couple things that i noticed that will help me in the future that i'm sure you can answer.

When should i use a try catch block within my code since it has a high overload?

Is it always a good idea to use the Using Block of code all the time and if so is it only recommended for the conn object? I still don't fully understand, sorry i'm still learning :(

Also, is there a reason that conn.Open is there and why is it needed without the conn.Close?

Thanks in advance!!!
The try catch block is a very good thing to use. You always want to provide the best user experience and handling unexpected exceptions is one way to do that.

The overhead for exception is not that bad, simply there is one. To be a better developer you consider these things and then make the best choice for your application. I suggested that it is better to handle exceptions in your business layer and leave your data access layer/logic to run as fast as possible.

It is always good idea to use the USING block if possible. Remember the using block can only be used on classes that implement the IDisposable interface like the SqlConnection or MemoryStream, etc. What happens is that whenever execution of the code exits the USING block the Dispose method is called and for the Connection object this method with close the connection.

I think its even possible not to call the conn.Open method (verifying is needed) since I believe the Command object will open it when executing.

Hope this helps.
Avatar of Brian

ASKER

DaTribe:

>> I suggested that it is better to handle exceptions in your business layer and leave your data access layer/logic to run as fast as possible

what is the difference between the business layer and the data access layer? Also, when you use the USING block why don't you need to add DIM either before or after it?

Is it a good idea to use USING for everything like DataSet, DataTable, and DataAdapter?

THANK YOU VERY MUCH IN ADVANCE!!
ASKER CERTIFIED SOLUTION
Avatar of Avodah
Avodah
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Brian

ASKER

Hi DaTribe,

I only have one more question before i close this post and that is, how can i find out what classes implement the IDisposable interface.
A comprehensive way to locate classes which implement the IDisposable interface is to use the Object Browser Ctrl+W,J. You should search All Component for IDisposable and the right click on the IDisposable interface and "find usages advanced". Select extending interfaces and Solution and Libraries.
Avatar of Brian

ASKER

THANK YOU FOR ALL YOUR HELP AND PATIENCE!!