nested select statements taking too long to load on SQL server
I have a page that displays reports on a grid. The grid uses an Object data source which is bound to a class that returns data. The class itself uses standard SQL query to return a count of records and binds to a dataview. The issue we are having is that it takes about 10 minutes sometimes to load and I know there has to be a better way but cannot for the life of me, figure out what. Hoping to get some insights from anyone on how to optimize this for performance. The data class is shown below: any feedback would be appreciated. There are about 650 attorneys returned by the attorney view which is bound to 2 tables: attorneys and locations table. The view on which the counts are performed on is bound to 2 tables also: current cases and previous cases tables and that returns about 125,000 cases total. Caching is out of the question because the end user will be able to supply any start and end dates to generate the report.
Dim PendingStringBuilder As String = "((dbo.cases.attorney_id = dbo.attorneys.att_id) AND (dbo.cases.date_assigned = @StartDate OR dbo.cases.closing_date IS NULL)) OR ((dbo.casepreviousattorneys.attorney_id = dbo.attorneys.att_id) AND (dbo.casepreviousattorneys.previous_assignment_date = @StartDate OR dbo.casepreviousattorneys.unassignment_date IS NULL))" Dim AssignedStringBuilder As String = "((dbo.cases.attorney_id = dbo.attorneys.att_id) AND (dbo.cases.date_assigned >= @StartDate) AND (dbo.cases.date_assigned = @StartDate) AND (dbo.casepreviousattorneys.previous_assignment_date Dim CountTable As String = " dbo.cases WITH (NOLOCK) INNER JOIN dbo.tlkpcasetype ON dbo.cases.case_type_id = dbo.tlkpcasetype.case_type_id FULL OUTER JOIN dbo.casepreviousattorneys ON dbo.cases.case_no = dbo.casepreviousattorneys.case_no" Dim dt As New DataTable("ReportTable") Dim dr As DataRow dt.Columns.Add("CasesPending", Type.[GetType]("System.Int32")) dt.Columns.Add("CasesAssigned", Type.[GetType]("System.Int32")) dt.Columns.Add("ProbationViolation", Type.[GetType]("System.Int32")) dt.Columns.Add("BailOnly", Type.[GetType]("System.Int32")) dt.Columns.Add("TotalCases", Type.[GetType]("System.Int32")) dt.Columns.Add("AttorneyID", Type.[GetType]("System.Int32")) dt.Columns.Add("AttorneyName", Type.[GetType]("System.String")) dt.Columns.Add("AttorneyFirstName", Type.[GetType]("System.String")) dt.Columns.Add("AttorneyLastName", Type.[GetType]("System.String")) dt.Columns.Add("UnitID", Type.[GetType]("System.Int32")) dt.Columns.Add("UnitName", Type.[GetType]("System.String")) dt.Columns.Add("UnitType", Type.[GetType]("System.String")) dt.Columns.Add("OfficeID", Type.[GetType]("System.Int32")) dt.Columns.Add("Office", Type.[GetType]("System.String")) If cn.State = ConnectionState.Closed Then cn.Open() Dim cmd As SqlCommand Dim rdr As SqlDataReader strSQL = "SELECT DISTINCT dbo.attorneys.user_id, dbo.attorneys.att_id AS AttorneyID, dbo.attorneys.first_name +' '+ dbo.attorneys.last_name AS AttorneyName, dbo.attorneys.unit_id AS UnitID, dbo.tlkpunit.unit AS UnitName, dbo.tlkpunit.unit_type AS UnitType, dbo.tlkpunit.office_id AS OfficeID, dbo.tlkpoffice.office AS Office, " strSQL += "(SELECT COUNT(DISTINCT dbo.cases.case_no) AS ExprCasesPending FROM " & CountTable & " WHERE (" & PendingStringBuilder & ")) As CasesPending, " strSQL += "(SELECT COUNT(DISTINCT dbo.cases.case_no) AS ExprCasesAssigned FROM " & CountTable & " WHERE (dbo.tlkpcasetype.case_type 'Probation Violation') AND (dbo.tlkpcasetype.case_type 'Bail Only') AND (" & AssignedStringBuilder & ")) As CasesAssigned, " strSQL += "(SELECT COUNT(DISTINCT dbo.cases.case_no) AS ExprProbationViolation FROM " & CountTable & " WHERE (dbo.tlkpcasetype.case_type = 'Probation Violation') AND (" & AssignedStringBuilder & ")) As ProbationViolation, " strSQL += "(SELECT COUNT(DISTINCT dbo.cases.case_no) AS ExprBailOnly FROM " & CountTable & " WHERE (dbo.tlkpcasetype.case_type = 'Bail Only') AND (" & AssignedStringBuilder & ")) As BailOnly, " strSQL += "(SELECT COUNT(DISTINCT dbo.cases.case_no) AS ExprTotalCases FROM " & CountTable & " WHERE (" & AssignedStringBuilder & ")) As TotalCases " strSQL += " FROM dbo.attorneys WITH (NOLOCK) LEFT OUTER JOIN dbo.tlkpunit ON dbo.attorneys.unit_id = dbo.tlkpunit.unit_id LEFT OUTER JOIN dbo.tlkpdivision ON dbo.tlkpunit.division_id = dbo.tlkpdivision.division_id LEFT OUTER JOIN dbo.tlkpoffice ON dbo.tlkpunit.office_id = dbo.tlkpoffice.office_id WHERE (dbo.tlkpunit.unit 'test-unit') " cmd = New SqlCommand(strSQL, cn) cmd.Parameters.AddWithValue("@StartDate", DateAStart) cmd.Parameters.AddWithValue("@EndDate", DateAEnd) rdr = cmd.ExecuteReader() While rdr.Read If rdr("CasesPending").ToString = 0 And rdr("CasesAssigned") = 0 And rdr("ProbationViolation").ToString = 0 And rdr("BailOnly") = 0 Then 'Do not add record Else dr = dt.NewRow() dr("CasesPending") = CInt(rdr("CasesPending")) dr("CasesAssigned") = CInt(rdr("CasesAssigned")) dr("ProbationViolation") = CInt(rdr("ProbationViolation")) dr("BailOnly") = CInt(rdr("BailOnly")) dr("TotalCases") = CInt(rdr("TotalCases")) dr("AttorneyID") = rdr("AttorneyID") dr("AttorneyName") = rdr("AttorneyName") dr("UnitID") = rdr("UnitID") dr("UnitName") = rdr("UnitName") dr("UnitType") = rdr("UnitType") dr("OfficeID") = rdr("OfficeID") dr("Office") = rdr("Office") dt.Rows.Add(dr) End If End While rdr.Close() cmd.Dispose() If cn.State = ConnectionState.Open Then cn.Close() Dim dv As New DataView(dt) dv.Sort = "AttorneyName ASC" Return dv
Read up on "sql execution plans" and you may want to review your table indexes. It is likely that these things will yield the greatest results. See this SQL Server Optimization MSDN article for more information.
I also notice in your VB code you are not parameterizing your SQL string. You should consider doing this after the above for additional performance benefit.
For more information on using SQL parameters see:
http://www.codinghorror.com/blog/2005/04/give-me-parameterized-sql-or-give-me-death.html http://technet.microsoft.com/en-us/library/ms186219.aspx
Try using a stored procedure. This will have the code compiled in the Sql Server already and the execution plan stored ahead of time. John
链接地址: http://www.djcxy.com/p/44028.html