Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ADO.NET SQL Server性能瓶颈_C#_Sql_Sql Server_Ado - Fatal编程技术网

C# ADO.NET SQL Server性能瓶颈

C# ADO.NET SQL Server性能瓶颈,c#,sql,sql-server,ado,C#,Sql,Sql Server,Ado,我有一个sql连接,我必须每秒访问数据库500到10000次。大约每秒250次之后,事情开始变慢,然后应用程序远远落后于它崩溃 我在考虑把数据库放进字典里。我需要最快的表现,我可以得到。目前ado.net大约需要1到2毫秒,但是发生了一些导致瓶颈的事情 对于每秒10k的查询,下面的语法是否有任何错误?字典有用吗?我们谈论的是1200万条记录,我需要能够在1到5毫秒内搜索它。数据库中还有另一个集合,有5000万条记录,所以我不知道如何存储它。任何建议都很好 SQL db有128 gb内存和80个处

我有一个sql连接,我必须每秒访问数据库500到10000次。大约每秒250次之后,事情开始变慢,然后应用程序远远落后于它崩溃

我在考虑把数据库放进字典里。我需要最快的表现,我可以得到。目前ado.net大约需要1到2毫秒,但是发生了一些导致瓶颈的事情

对于每秒10k的查询,下面的语法是否有任何错误?字典有用吗?我们谈论的是1200万条记录,我需要能够在1到5毫秒内搜索它。数据库中还有另一个集合,有5000万条记录,所以我不知道如何存储它。任何建议都很好

SQL db有128 gb内存和80个处理器,应用程序位于SQL server 2012上的同一台服务器上

   using (SqlConnection sqlconn = new SqlConnection(sqlConnection.SqlConnectionString()))
   {
       using (SqlCommand sqlcmd = new SqlCommand("", sqlconn))
       {
           sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
           sqlcmd.Parameters.Clear();
           sqlcmd.CommandTimeout = 1;
           sqlconn.Open();
           using (SqlDataReader sqlDR = sqlcmd.ExecuteReader(CommandBehavior.CloseConnection))


    public static string SqlConnectionString()
    {
        return string.Format("Data Source={0},{1};Initial Catalog={2};User ID={3};Password={4};Application Name={5};Asynchronous Processing=true;MultipleActiveResultSets=true;Max Pool Size=524;Pooling=true;",
                    DataIP, port, Database, username, password, IntanceID);
    }
datareader下面的代码是

r.CustomerInfo = new CustomerVariable();
r.GatewayRoute = new List<RoutingGateway>();
while (sqlDR.Read() == true)
{

    if (sqlDR["RateTableID"] != null)
        r.CustomerInfo.RateTable = sqlDR["RateTableID"].ToString();
    if (sqlDR["EndUserCost"] != null)
        r.CustomerInfo.IngressCost = sqlDR["EndUserCost"].ToString();
    if (sqlDR["Jurisdiction"] != null)
        r.CustomerInfo.Jurisdiction = sqlDR["Jurisdiction"].ToString();
    if (sqlDR["MinTime"] != null)
        r.CustomerInfo.MinTime = sqlDR["MinTime"].ToString();
    if (sqlDR["interval"] != null)
        r.CustomerInfo.interval = sqlDR["interval"].ToString();
    if (sqlDR["code"] != null)
        r.CustomerInfo.code = sqlDR["code"].ToString();
    if (sqlDR["BillBy"] != null)
        r.CustomerInfo.BillBy = sqlDR["BillBy"].ToString();
    if (sqlDR["RoundBill"] != null)
        r.CustomerInfo.RoundBill = sqlDR["RoundBill"].ToString();

}
sqlDR.NextResult();
r.CustomerInfo=新的CustomerVariable();
r、 网关路由=新列表();
while(sqlDR.Read()==true)
{
如果(sqlDR[“RateTableID”]!=null)
r、 CustomerInfo.RateTable=sqlDR[“RateTableID”].ToString();
如果(sqlDR[“EndUserCost”]!=null)
r、 CustomerInfo.ingrescost=sqlDR[“EndUserCost”].ToString();
if(sqlDR[“辖区”]!=null)
r、 CustomerInfo.directory=sqlDR[“辖区”].ToString();
if(sqlDR[“MinTime”]!=null)
r、 CustomerInfo.MinTime=sqlDR[“MinTime”].ToString();
if(sqlDR[“interval”]!=null)
r、 CustomerInfo.interval=sqlDR[“interval”].ToString();
if(sqlDR[“code”]!=null)
r、 CustomerInfo.code=sqlDR[“code”].ToString();
如果(sqlDR[“BillBy”]!=null)
r、 CustomerInfo.BillBy=sqlDR[“BillBy”].ToString();
if(sqlDR[“整单”]!=null)
r、 CustomerInfo.RoundBill=sqlDR[“RoundBill”].ToString();
}
sqlDR.NextResult();

如果您已经测量到ADO命令只需要几毫秒,那么造成延迟的另一个可能原因是用于构建connectionstring的string.Format

我将尝试删除为每个

using(SqlConnection cn = new SqlConnection(sqlConnection.SqlConnectionString()))
相反,假设SqlConnectionString位于单独的类中,您可以编写

private static string conString = string.Empty;
public static string SqlConnectionString()
{
    if(conString == "")
       conString = string.Format("............");
    return conString;
}
当然,基准测试可以排除这一点,但我非常确信,像这样的字符串操作代价高昂

在下面看到您的评论另一件非常重要的事情是添加正确的参数声明。不要使用AddWithValue(方便但有棘手的副作用),而是用正确的大小声明参数

using (SqlCommand sqlcmd = new SqlCommand("", sqlconn))
{
    sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
    sqlcmd.CommandText = mySql.GetLCR(); 
    SqlParameter p1 = new SqlParameter("@GatewayID", SqlDbType.NVarChar, 20).Value = GatewayID; 
    SqlParameter p2 = new SqlParameter("@DialNumber", SqlDbType.NVarChar, 20).Value = dialnumber; 
    sqlCmd.Parameters.AddRange(new SqlParameter[] {p1, p2});
    sqlcmd.CommandTimeout = 1;
    sqlconn.Open();
    .....
}

当需要压缩每毫秒的性能时,不建议使用AddWithValue。解释为什么传递带有AddWithValue的字符串会破坏Sql Server优化器所做的工作。(简而言之,优化器为您的命令计算并存储一个查询计划,如果它收到另一个相同的命令,它将重用计算的查询计划。但是,如果您传递一个带有addwithvalue的字符串,则每次都会根据实际传递的字符串长度计算参数的大小。优化器无法重用查询计划和recalc创建并存储一个新命令)

如果您已经测量到ADO命令只需要几毫秒,那么另一个可能的延迟原因是用于构建connectionstring的string.Format

我将尝试删除为每个

using(SqlConnection cn = new SqlConnection(sqlConnection.SqlConnectionString()))
相反,假设SqlConnectionString位于单独的类中,您可以编写

private static string conString = string.Empty;
public static string SqlConnectionString()
{
    if(conString == "")
       conString = string.Format("............");
    return conString;
}
当然,基准测试可以排除这一点,但我非常确信,像这样的字符串操作代价高昂

在下面看到您的评论另一件非常重要的事情是添加正确的参数声明。不要使用AddWithValue(方便但有棘手的副作用),而是用正确的大小声明参数

using (SqlCommand sqlcmd = new SqlCommand("", sqlconn))
{
    sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
    sqlcmd.CommandText = mySql.GetLCR(); 
    SqlParameter p1 = new SqlParameter("@GatewayID", SqlDbType.NVarChar, 20).Value = GatewayID; 
    SqlParameter p2 = new SqlParameter("@DialNumber", SqlDbType.NVarChar, 20).Value = dialnumber; 
    sqlCmd.Parameters.AddRange(new SqlParameter[] {p1, p2});
    sqlcmd.CommandTimeout = 1;
    sqlconn.Open();
    .....
}

当需要压缩每毫秒的性能时,不建议使用AddWithValue。解释为什么传递带有AddWithValue的字符串会破坏Sql Server优化器所做的工作。(简而言之,优化器为您的命令计算并存储一个查询计划,如果它收到另一个相同的命令,它将重用计算的查询计划。但是,如果您传递一个带有addwithvalue的字符串,则每次都会根据实际传递的字符串长度计算参数的大小。优化器无法重用查询计划和recalc创建并存储一个新的)

我认为问题不在于string.format

结果是:

格式为108毫秒

公开赛1416毫秒

5176毫秒用于执行

整个过程是6891毫秒

运行这个,非常简单的测试

namespace ConsoleApplication1
{
    class Program
    {
        private static string DataIP;        
        private static string Database;          
        private static string IntanceID;

        static void Main(string[] args)
        {
            DataIP = @"FREDOU-PC\SQLEXPRESS";  Database = "testing"; IntanceID = "123";
            int count = 0;
            System.Diagnostics.Stopwatch swWholeThing = System.Diagnostics.Stopwatch.StartNew();

            System.Diagnostics.Stopwatch swFormat = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swOpen = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swExecute = new System.Diagnostics.Stopwatch();

            for (int i = 0; i < 100000; ++i)
            {
                using (System.Data.SqlClient.SqlConnection sqlconn = new System.Data.SqlClient.SqlConnection(SqlConnectionString(ref swFormat)))
                {
                   using (System.Data.SqlClient.SqlCommand sqlcmd = new System.Data.SqlClient.SqlCommand("dbo.counttable1", sqlconn))
                   {
                       sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
                       sqlcmd.Parameters.Clear();
                       swOpen.Start();
                       sqlconn.Open();
                       swOpen.Stop();
                       swExecute.Start();

                       using (System.Data.SqlClient.SqlDataReader sqlDR = sqlcmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                       {
                           if (sqlDR.Read())
                            count += sqlDR.GetInt32(0);
                       }

                       swExecute.Stop();
                    }
                }                
            }

            swWholeThing.Stop();
            System.Console.WriteLine("swFormat: " + swFormat.ElapsedMilliseconds);
            System.Console.WriteLine("swOpen: " + swOpen.ElapsedMilliseconds);
            System.Console.WriteLine("swExecute: " + swExecute.ElapsedMilliseconds);
            System.Console.WriteLine("swWholeThing: " + swWholeThing.ElapsedMilliseconds + " " + count);

            System.Console.ReadKey();
        }

        public static string SqlConnectionString(ref System.Diagnostics.Stopwatch swFormat)
        {
            swFormat.Start();
            var str =  string.Format("Data Source={0};Initial Catalog={1};Integrated Security=True;Application Name={2};Asynchronous Processing=true;MultipleActiveResultSets=true;Max Pool Size=524;Pooling=true;",
                        DataIP,  Database, IntanceID);
            swFormat.Stop();
            return str;
        }
    }
}
dbo.table_1

USE [testing]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_1](
    [id] [int] NOT NULL,
 CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
内容:

insert into dbo.Table_1 (id) values (1)
insert into dbo.Table_1 (id) values (2)
insert into dbo.Table_1 (id) values (3)
insert into dbo.Table_1 (id) values (4)
insert into dbo.Table_1 (id) values (5)
insert into dbo.Table_1 (id) values (6)
insert into dbo.Table_1 (id) values (7)
insert into dbo.Table_1 (id) values (8)
insert into dbo.Table_1 (id) values (9)
insert into dbo.Table_1 (id) values (10)

我认为问题不在于string.format

结果是:

格式为108毫秒

公开赛1416毫秒

5176毫秒用于执行

整个过程是6891毫秒

运行这个,非常简单的测试

namespace ConsoleApplication1
{
    class Program
    {
        private static string DataIP;        
        private static string Database;          
        private static string IntanceID;

        static void Main(string[] args)
        {
            DataIP = @"FREDOU-PC\SQLEXPRESS";  Database = "testing"; IntanceID = "123";
            int count = 0;
            System.Diagnostics.Stopwatch swWholeThing = System.Diagnostics.Stopwatch.StartNew();

            System.Diagnostics.Stopwatch swFormat = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swOpen = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swExecute = new System.Diagnostics.Stopwatch();

            for (int i = 0; i < 100000; ++i)
            {
                using (System.Data.SqlClient.SqlConnection sqlconn = new System.Data.SqlClient.SqlConnection(SqlConnectionString(ref swFormat)))
                {
                   using (System.Data.SqlClient.SqlCommand sqlcmd = new System.Data.SqlClient.SqlCommand("dbo.counttable1", sqlconn))
                   {
                       sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
                       sqlcmd.Parameters.Clear();
                       swOpen.Start();
                       sqlconn.Open();
                       swOpen.Stop();
                       swExecute.Start();

                       using (System.Data.SqlClient.SqlDataReader sqlDR = sqlcmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection))
                       {
                           if (sqlDR.Read())
                            count += sqlDR.GetInt32(0);
                       }

                       swExecute.Stop();
                    }
                }                
            }

            swWholeThing.Stop();
            System.Console.WriteLine("swFormat: " + swFormat.ElapsedMilliseconds);
            System.Console.WriteLine("swOpen: " + swOpen.ElapsedMilliseconds);
            System.Console.WriteLine("swExecute: " + swExecute.ElapsedMilliseconds);
            System.Console.WriteLine("swWholeThing: " + swWholeThing.ElapsedMilliseconds + " " + count);

            System.Console.ReadKey();
        }

        public static string SqlConnectionString(ref System.Diagnostics.Stopwatch swFormat)
        {
            swFormat.Start();
            var str =  string.Format("Data Source={0};Initial Catalog={1};Integrated Security=True;Application Name={2};Asynchronous Processing=true;MultipleActiveResultSets=true;Max Pool Size=524;Pooling=true;",
                        DataIP,  Database, IntanceID);
            swFormat.Stop();
            return str;
        }
    }
}
dbo.table_1

USE [testing]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_1](
    [id] [int] NOT NULL,
 CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
内容:

insert into dbo.Table_1 (id) values (1)
insert into dbo.Table_1 (id) values (2)
insert into dbo.Table_1 (id) values (3)
insert into dbo.Table_1 (id) values (4)
insert into dbo.Table_1 (id) values (5)
insert into dbo.Table_1 (id) values (6)
insert into dbo.Table_1 (id) values (7)
insert into dbo.Table_1 (id) values (8)
insert into dbo.Table_1 (id) values (9)
insert into dbo.Table_1 (id) values (10)

如果要在循环中访问DataReader,那么应该在循环外找到索引,然后在循环内使用它们。您还可以更好地使用强类型ACCESOR。

如果要在循环中访问DataReader,那么应该在循环外找到索引,然后在循环内使用它们。您还可以更好地使用强类型ACCESOR

  • 不要关闭并重新打开连接,您可以在请求之间保持连接打开。即使打开了连接池,也会有一定的开销,包括一个简短的关键部分,用于在从池中捕获连接时防止并发问题。还是避免吧

  • 确保存储过程已设置NOCOUNT以减少聊天次数

  • 确保您使用的是可以避免的最低事务隔离级别,例如脏读或NOLOCK。你可以在