0

我有一个在网格上显示报告的页面。网格使用绑定到返回数据的类的对象数据源。该类本身使用标准 SQL 查询来返回记录计数并绑定到数据视图。我们遇到的问题是,有时加载大约需要 10 分钟,我知道必须有更好的方法,但我一辈子都做不到,弄清楚是什么。希望从任何人那里获得一些关于如何优化性能的见解。数据类如下所示:任何反馈将不胜感激。律师视图返回了大约 650 名律师,绑定到 2 个表:律师和位置表。对其执行计数的视图也绑定到 2 个表:当前案例和以前的案例表,总共返回大约 125,000 个案例。

Dim PendingStringBuilder As String = "((dbo.cases.attorney_id = dbo.attorneys.att_id) AND (dbo.cases.date_assigned <= @StartDate) AND (dbo.cases.closing_date >= @StartDate OR dbo.cases.closing_date IS NULL)) OR ((dbo.casepreviousattorneys.attorney_id =
 dbo.attorneys.att_id) AND (dbo.casepreviousattorneys.previous_assignment_date <= @StartDate) AND (dbo.casepreviousattorneys.unassignment_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 <= @EndDate)) OR ((dbo.casepreviousattorneys.attorney_id = dbo.attorneys.att_id) AND (dbo.casepreviousattorneys.previous_assignment_date
 >= @StartDate) AND (dbo.casepreviousattorneys.previous_assignment_date <= @EndDate))"

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
4

2 回答 2

1

阅读“sql 执行计划”,您可能需要查看表索引。这些事情很可能会产生最大的结果。有关详细信息,请参阅此SQL Server 优化 MSDN 文章

我还注意到在你的 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

于 2012-04-12T22:53:44.570 回答
-1

尝试使用存储过程。这将已经在 Sql Server 中编译了代码,并提前存储了执行计划。约翰

于 2015-03-30T16:58:49.890 回答