【问题标题】:Sloq SQL execution (calling store procedures) on huge site在大型站点上执行缓慢的 SQL(调用存储过程)
【发布时间】:2016-01-13 12:01:46
【问题描述】:

首先,我意识到我的问题可能很宽泛,请多多包涵,因为我已经思考了一个月如何形成它,但我仍然不能 100% 确定如何表达我的问题。

我目前正在开发一个网站,每天将有成千上万的用户使用该网站。瓶颈是与数据库的通信。

与表的每次对话都是通过存储过程完成的,其调用如下所示:

    public void storedProcedure(int id, out DataSet ds)
{
    ds = new DataSet("resource");

    SqlDataReader objReader = null;
    SqlCommand cmd = new SqlCommand("storedProcedure", DbConn.objConn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@id", id));

    openConnection(cmd);

    SqlDataAdapter objDataAdapter = new SqlDataAdapter();
    objDataAdapter.SelectCommand = cmd;

    objDataAdapter.Fill(ds);

    cmd.Connection.Close();
}

或者

   public void anotherStoredProcedure(int var1, int var2, int var3, int var4, string var5,  out DataSet ds)
{
    ds = new DataSet("ai");

    SqlCommand cmd = new SqlCommand("anotherStoredProcedure", DbConn.objConn);
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Add(new SqlParameter("@var1", var1));
    cmd.Parameters.Add(new SqlParameter("@var2", var2));
    cmd.Parameters.Add(new SqlParameter("@var3", var3));
    cmd.Parameters.Add(new SqlParameter("@var4", var4));
    cmd.Parameters.Add(new SqlParameter("@var5", var5));

    openConnection(cmd);


    SqlDataAdapter objDataAdapter = new SqlDataAdapter();
    objDataAdapter.SelectCommand = cmd;
    objDataAdapter.Fill(ds);

    cmd.Connection.Close();

}

我的 objConn 定义如下:

    public static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["objConnLocal"].ConnectionString;
public static SqlConnection objConn = new SqlConnection(DatabaseConnectionString);

当然在 web.config 我有

<add name="objConnLocal" connectionString="Initial Catalog=t1;Data Source=1.2.3.4;Uid=id;pwd=pwd;Min Pool Size=20;Max Pool Size=200;" providerName="SQLOLEDB.1"/>

现在的问题是:在每个 page_load 上都有一些 sp 调用(上图),当用户开始浏览页面时,会进行更多调用。

目前只有开发和测试团队在网站上,有时速度真的很慢。通常它会一直加载直到超时(错误 504)。

第一次用户登录时的另一个问题(只是偶尔出现,但肯定频繁到足以引起注意)是它会继续尝试运行呼叫,但连接会声称已打开,即使它不应该打开。一个相当无效的解决方法是

private void openConnection(SqlCommand cmd){

    if (cmd.Connection.State != ConnectionState.Closed)
    {
        cmd.Connection.Close();
    }

    if (cmd.Connection.State == ConnectionState.Open)
    {
        cmd.Connection.Close();
    }
    try
    {
        cmd.Connection.Open();
    }
    catch (Exception ex)
    {
        System.Threading.Thread.Sleep(1000);
        HttpContext.Current.Response.Redirect("/");
    }
}

这使得连接速度变慢,但至少不显示 YSOD。

那么,我在我的 SQL 调用上做错了什么,以至于只有 5-10 个用户的速度如此之慢?到目前为止我所拥有的: 我在 Stack Overflow 上读到使用“使用”非常好,但我不完全确定为什么以及如何出现,因为它是答案下的单行注释。另一个改进的想法是使用多个连接字符串,而不仅仅是一个。

已解决:

将连接字符串中的等待连接建立从用户名/密码更改为集成安全解决了该问题。如果有人遇到类似问题,请参考http://www.codeproject.com/Articles/17768/ADO-NET-Connection-Pooling-at-a-Glance

【问题讨论】:

    标签: c# sql asp.net sql-server stored-procedures


    【解决方案1】:

    你是对的 - 这是一个广泛的问题!

    对于上下文 - 从性能的角度来看,许多“每天有成千上万的用户”并不算多。一个精心构建的 ASP.Net 应用程序通常可以在一台体面指定的开发人员笔记本电脑上支持数百个并发用户;假设每天有 10,000 个用户,您在高峰期可能只有几十个并发用户(当然这完全取决于应用程序域)。

    首先要做的是对正在运行的代码使用分析器来查看性能瓶颈在哪里。这是available in VS,有几个第三方解决方案(我喜欢 RedGate 和 JetBrains)。

    分析器会告诉您代码慢的地方 - 如果页面渲染需要几秒钟,这应该很明显。

    乍一看,您的数据库似乎有问题。因此,您还可以使用SQLServer activity monitor 查看长时间运行的查询。

    【讨论】:

    • 我会阅读分析器来设置它,谢谢。活动监视器也可能有很大帮助!
    • 我终于找到了问题所在。我们有一个程序在 15 到 25 秒内被破坏了很长一段时间,并且网站正在超时,等待它。现在主要问题是我们在连接字符串中使用了 user_id 和密码来连接数据库,因此所有用户总共有 200 个连接。如果我们没有这个长时间运行的 SQL,这几乎不是问题。但既然我们这样做了,我们就引入了集成安全性 - 为每个用户提供一个新的连接池,因为上面的所有问题都消失了。
    • 您仍然在谈论少量用户。 20 个连接 - 哇哦。严重地。修复损坏的存储过程。它不应该花费 15-25 秒——不知何故,我认为数据库程序员犯了初学者的错误。缺少索引、不可存储的 sql 之类的东西。解决这个问题。
    【解决方案2】:

    现在的问题是:在每个 page_load 上都有几个 sp 调用(上图),并且 当用户开始浏览页面时,会进行更多调用。

    这听起来就像您编写的网页在存储过程调用完成之前不会显示任何内容。这绝不是一个好主意。

    将这些 SP 调用转移到后台线程中,这样用户在进入网页时至少会看到一些内容(例如“请稍候”消息)。这也有助于防止出现超时消息。

    另一件事:你没有说为什么你的 SP 需要这么长时间才能运行。

    如果您要处理大量记录,则值得运行 SQL 脚本(在下面的链接中描述)来检查丢失的 SQL Server 索引。

    Finding missing indexes

    此脚本显示对您的用户影响最大的缺失索引,还告诉您添加这些索引需要运行的 CREATE INDEX 命令的语法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 2011-06-27
      • 2016-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      相关资源
      最近更新 更多