优化长时间运行的更新查询

时间:2011-10-18 04:39:40

标签: asp.net sql-server

我用三个sql查询编写了以下方法,以便更新单个表中的单个列。因为有近10000条记录需要更新,所以需要20多分钟才能完成。还有其他更好的方法吗这个更新。有点像基于集合的更新......

private void UpdateLatest()
    {
        string connstr = "Data Source=CHAMARA-PC;Initial Catalog=PHPA_Production_fromEWP;Integrated Security=True";
        using (SqlConnection conn = new SqlConnection(connstr))
        {
            conn.Open();
            SqlTransaction myTransaction = conn.BeginTransaction();
            try
            {
                DataTable dt = new DataTable();
                DataTable DTT = new DataTable();

                string command = "select dh.DocumentNumber,max(dr.RevisionDate) as latestdate from " +
                  "tblDocumentHeader dh inner join tblDocumentRevision dr on dh.DocumentHeaderID=dr.DocumentHeaderID " +
                      "group by dh.DocumentNumber ";


                using (SqlCommand cmd = new SqlCommand(command, conn, myTransaction))
                {
                    using (SqlDataAdapter adapt = new SqlDataAdapter())
                    {
                        adapt.SelectCommand = cmd;
                        adapt.Fill(dt);

                    }
                }
                label1.Text = dt.Rows.Count.ToString();
                foreach (DataRow item in dt.Rows)
                {
                    try
                    {
                        int res = 0;
                        string query2 = "select dr.DocumentRevisionID from " +
                  "tblDocumentHeader dh inner join tblDocumentRevision dr on dh.DocumentHeaderID=dr.DocumentHeaderID " +
                  " where dh.DocumentNumber='" + item["DocumentNumber"].ToString().Trim() + "' and dr.RevisionDate='" + item["latestdate"].ToString().Trim() + "'";

                        using (SqlCommand cmd = new SqlCommand(query2, conn, myTransaction))
                        {
                            using (SqlDataAdapter adapt = new SqlDataAdapter())
                            {
                                adapt.SelectCommand = cmd;
                                adapt.Fill(DTT);

                            }
                        }

                        foreach (DataRow Ritem in DTT.Rows)
                        {
                            string updatequery = "update tblDocumentRevision set LatestRev='latest' where DocumentRevisionID='" + Ritem["DocumentRevisionID"].ToString().Trim() + "'";

                            using (SqlCommand cmd = new SqlCommand(updatequery, conn, myTransaction))
                            {
                                cmd.ExecuteNonQuery();

                                res++;

                            }
                        }
                        listBox1.Items.Add(item["DocumentNumber"].ToString() + " " + "updated");

                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
                myTransaction.Commit();
                MessageBox.Show("successfully updated");
            }
            catch (Exception ex)
            {
                myTransaction.Rollback();
                MessageBox.Show(ex.Message);

            }
        }
    }

2 个答案:

答案 0 :(得分:3)

我手边没有你的数据库来测试这个,但基本上,你的代码归结为:

DECLARE @Temp TABLE (DocNumber INT, LatestDate DATETIME)

INSERT INTO @Temp(DocNumber, LatestDate)
    SELECT 
        dh.DocumentNumber, MAX(dr.RevisionDate) 
    FROM 
        dbo.tblDocumentHeader dh 
    INNER JOIN 
        dbo.tblDocumentRevision dr ON dh.DocumentHeaderID = dr.DocumentHeaderID
    GROUP BY 
        dh.DocumentNumber

UPDATE 
    dbo.tblDocumentRevision 
SET 
    LatestRev = 'latest' 
FROM
    dbo.tblDocumentRevision dr
INNER JOIN
    dbo.tblDocumentHeader dh ON dh.DocumentHeaderID = dr.DocumentHeaderID 
INNER JOIN
    @Temp t ON dh.DocumentNumber = t.DocNumber AND dr.RevisionDate = t.LatestDate

这可以很容易地包装在存储过程中,使用任何死慢游标,并且导致任何SQL注入可能性。

答案 1 :(得分:2)

  

因为有近10000条记录需要更新,所以需要20多分钟才能完成

学习SQL。

好的,首先 - 10.000更新语句= 20分钟表示您的服务器是带有慢速光盘的笔记本电脑,而不是数据库服务器。这太长了。你做的方式是可怕的慢,但最后...... 20分钟太慢了。如果这是一个真正的数据库 - 为它获取服务器。您每秒执行的更新少于10次,即使普通桌面也可以处理大约75次。

现在:

您选择然后更新。为什么?为什么不

  

更新tblDocumentRevision设置LatestRev ='latest',其中DocumentRevisionID IN(x,y,z)

并且每100个左右的文件开一次?这粗暴地减少了你发表的声明数量。

如果那个母猪过于播种,你应该将它们从异步中激活 - 在语句1执行时准备语句2,或者甚至并行地从多个工作线程中激活它们。

最后,SQL基础知识:DocumentRevisionID上有索引吗? 第三,这里不需要使用适配器和dta表。这是一种笨拙,笨拙,通常会避免正确的编程习惯。