2012-04-12 3 views
0

그리드에 대한 보고서를 표시하는 페이지가 있습니다. 그리드는 데이터를 반환하는 클래스에 바인딩 된 Object 데이터 소스를 사용합니다. 클래스 자체는 표준 SQL 쿼리를 사용하여 레코드 수를 반환하고 데이터 뷰에 바인딩합니다. 우리가 겪고있는 문제는 때때로로드하는 데 약 10 분이 걸리고 더 나은 방법이 있어야한다는 것을 알지만 내 인생에는 할 수 없다는 것입니다. 성능 최적화를 위해 다른 사람들로부터 통찰력을 얻기를 바랍니다. 데이터 클래스는 아래와 같습니다 : 모든 의견을 부탁드립니다. 변호사와 위치 테이블은 2 개의 테이블에 묶여있는 변호사의 견해에 의해 반환 된 약 650 명의 변호사가 있습니다. 카운트가 수행되는 뷰는 2 개의 테이블에도 바인딩됩니다. 현재 사례 및 이전 사례 테이블은 총 125,000 개의 사례를 반환합니다. 최종 사용자가 시작 및 종료 날짜를 제공하여 보고서를 생성 할 수 있기 때문에 캐싱 문제는 중요하지 않습니다.중첩 된 선택 문이 SQL 서버에로드하는 데 너무 오래 걸림

 

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 

+0

아마도 이러한 하위 선택과 관련이 있습니다. SQL을 단독으로 실행 해 보았습니까? 같은 문제가 계속 발생합니까? – sennett

+0

일종의 페이징 알고리즘을 사용하여 전체 집합이 아닌 한 번에 몇 행의 데이터 만로드한다고 생각해 봤습니까? –

답변

1

"SQL 실행 계획"을 읽고 테이블 색인을 검토 할 수 있습니다. 이러한 일이 가장 큰 결과를 낳을 수 있습니다. 자세한 내용은 SQL Server Optimization MSDN article을 참조하십시오.

또한 VB 코드에서 SQL 문자열을 매개 변수화하지 않음을 알 수 있습니다. 성능 향상을 위해 위의 작업을 수행해야합니다. SQL 매개 변수를 사용하는 방법에 대한 자세한 내용은

은 다음을 참조하십시오

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

+1

매개 변수화는 SQL 주입 공격으로부터 사용자를 보호합니다. –

+0

사실, 그래서 내가 코딩 호러 블로그에 대한 링크를 제공 이유입니다! –

+0

안녕하세요, 안녕하세요. 답변 해 주셔서 감사합니다. 변호사, 사례 및 이전 사례 테이블에 색인을 추가했습니다. 유닛, 사무실 또는 부서와 같은 더 작은 테이블은 각각 ​​200 개 미만의 레코드가 포함되어 있으므로 인덱싱하지 않았습니다 (중요한지 확실하지 않음). 로드하는 데 약 10 분이 소요됩니다. 또한 뷰 대신 테이블에서 직접 필요한 열만 선택하도록 SQL 문을 변경했지만 도움이되지 않았습니다. 다음은 업데이트 된 코드입니다. –

-1

가 저장 프로 시저를 사용하십시오. 이것은 이미 Sql Server에서 컴파일 된 코드와 미리 저장된 실행 계획을 갖게됩니다. John

+0

이것이 더 나은 경로라고 생각하는 이유에 대해 더 자세히 설명해 주시겠습니까? – MattD

+0

-1 캐시 된 계획이 누락되어 있지만 중복 된 중첩 된 subselect가있는 문제는 없습니다. 저장 프로 시저는 잘못 작성된 쿼리에 대한 솔루션이 아닙니다. – Matthew

관련 문제