与直接在 SQL Server 上执行相比,从 ASP.NET MVC Web 应用程序执行查询的执行速度明显慢

问题描述 投票:0回答:1

与直接在数据库上运行相比,从 ASP.NET MVC Web 应用程序执行 SQL 查询时,我遇到了明显的性能问题。

该查询应该检索大约 40,000 行,当直接在数据库上运行时,它会在大约 5 秒内完成。

但是,当使用以下 C# 函数从我的 Web 应用程序执行相同的查询时,大约需要 23 秒才能完成。

为什么差别这么大?

已采取的步骤:

  • 查询验证:我已经检查了查询日志记录,以确保 Web 应用程序正确发送查询,包括数据类型一致性,并且一切都按预期显示。
  • 数据转换:为了确定数据转换是否会减慢速度,我修改了函数以将所有列直接转换为字符串,绕过对日期/时间列(如
    ek_start_datetime
    )的任何特定检查。此更改仅将性能提高了约 1.5 秒。
public static List<Dictionary<string, string>> GetData(List<string> columns, string query)
{ 
    List<Dictionary<string, string>> data = new List<Dictionary<string, string>>();

    using (SqlConnection con = new SqlConnection(CS))
    {
        SqlCommand cmd2 = new SqlCommand(query, con);
        cmd2.CommandType = CommandType.Text;
        cmd2.CommandTimeout = 200;

        con.Open();

        SqlDataReader rdr = cmd2.ExecuteReader();

        while (rdr.Read())
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            foreach (string column in columns)
            {
                if (rdr[column] == null)
                {
                    dict.Add(column, "");
                }
                else if (column.Contains("ek_start_datetime"))
                {
                    dict.Add(column, ((DateTime)rdr[column]).ToString("yyyy-MM-dd HH:mm:ss.fff"));
                }
                else if (column.Contains("_startdatetime") && DateTime.TryParse(Convert.ToString(rdr[column]), out DateTime res))
                {
                    dict.Add(column, ((DateTime)rdr[column]).ToString("yyyy-MM-dd HH:mm:ss.fff"));
                }
                else if (column.Contains("_datetime") && DateTime.TryParse(Convert.ToString(rdr[column]), out DateTime res2))
                {
                    dict.Add(column, ((DateTime)rdr[column]).ToString("yyyy-MM-dd HH:mm:ss.fff"));
                }
                else if (column.Contains("_date") && DateTime.TryParse(Convert.ToString(rdr[column]), out DateTime result))
                {
                    dict.Add(column, result.ToString("yyyy-MM-dd"));
                }
                else
                {
                    dict.Add(column, Convert.ToString(rdr[column]));
                }
            }

            data.Add(dict);
        }
    }

    return data;
}

编辑

我发送的查询是一个字符串,其全局布局为:

SELECT 
    tv.column1, 
    tv.column2, 
    -- ...
    tv.column80, 
FROM 
    table1 tv
WHERE 
    tv.actual_flag = CAST(1 AS INT)
    AND tv.theme = CAST("theme1" AS varchar(10))
    AND tv.year as CAST(2024 AS INT)

当我在 SSMS 中执行相同的查询并查看查询计划时,它已正确优化

c# sql-server asp.net-mvc
1个回答
1
投票

以下

SET
选项有可能影响计划的重新使用

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
SET ARITHABORT ON
GO

以下两条语句来自msdn - SET ARITHABORT

将 ARITHABORT 设置为 OFF 会对查询优化产生负面影响,从而导致性能问题。

SQL Server Management Studio 的默认 ARITHABORT 设置为 ON。将 ARITHABORT 设置为 OFF 的客户端应用程序可以接收不同的查询计划,从而难以对性能不佳的查询进行故障排除。也就是说,相同的查询在 Management Studio 中执行速度很快,但在应用程序中执行速度很慢。

要将数据库设置为此,您只需在 SSMS 中使用一次

USE master 
ALTER DATABASE [your_database_name] SET ARITHABORT ON WITH NO_WAIT 
© www.soinside.com 2019 - 2024. All rights reserved.