Sql server 数据库性能性能差异:许多小型操作与一些大型操作

Sql server 数据库性能性能差异:许多小型操作与一些大型操作,sql-server,performance,entity-framework,performance-testing,database-performance,Sql Server,Performance,Entity Framework,Performance Testing,Database Performance,我目前正在调试一个应用程序的一些性能问题,该应用程序是在.net内核中构建的,使用SQL Server作为底层数据库,实体框架内核作为ORM 我编写了一个小型控制台应用程序来模拟一些工作负载: SqlConnection sqlConnection1; sqlConnection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=Database;Integrated Security=True;Mult

我目前正在调试一个应用程序的一些性能问题,该应用程序是在.net内核中构建的,使用SQL Server作为底层数据库,实体框架内核作为ORM

我编写了一个小型控制台应用程序来模拟一些工作负载:

SqlConnection sqlConnection1;      

sqlConnection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=Database;Integrated Security=True;MultipleActiveResultSets=true");

SqlCommand cmd = new SqlCommand();
SqlDataReader reader;

Console.WriteLine("==== Table1 (1000000) key-lookup ====");

var sw1 = new Stopwatch();
sw1.Start();

for (int i = 0; i < 1000000; i++)
{
     cmd.CommandText = "SELECT Value FROM table1 WHERE Id='" + i + "'";
     cmd.CommandType = CommandType.Text;
     cmd.Connection = sqlConnection1;

     sqlConnection1.Open();

     reader = cmd.ExecuteReader();

     var result = reader.Read();

     if (result)
     {
         var test = reader.GetString(0);
     }

     sqlConnection1.Close();
}

sw1.Stop();

Console.WriteLine("Finished: " + sw1.Elapsed);
Console.WriteLine("==== Table2 (1000) full-text-scan ====");

var sw2 = new Stopwatch();
sw2.Start();

for (int i = 0; i < 1000; i++)
{
    cmd.CommandText = "SELECT Name FROM table2 WHERE Name LIKE '%" + i + "%'";
    cmd.CommandType = CommandType.Text;
    cmd.Connection = sqlConnection1;

    sqlConnection1.Open();

    reader = cmd.ExecuteReader();

    var result = reader.Read();

    if (result)
    {
        var test = reader.GetString(0);
    }

    sqlConnection1.Close();
}

sw2.Stop();

Console.WriteLine("Finished: " + sw2.Elapsed);
Console.ReadKey();
SqlConnection-sqlConnection1;
sqlConnection1=新的SqlConnection(“数据源=。\\SQLEXPRESS;初始目录=数据库;集成安全性=True;MultipleActiveResultSets=True”);
SqlCommand cmd=新的SqlCommand();
SqlDataReader;
Console.WriteLine(“==Table1(1000000)键查找===”;
var sw1=新秒表();
sw1.Start();
对于(int i=0;i<1000000;i++)
{
cmd.CommandText=“从表1中选择值,其中Id=”+i+”;
cmd.CommandType=CommandType.Text;
cmd.Connection=sqlConnection1;
sqlConnection1.Open();
reader=cmd.ExecuteReader();
var result=reader.Read();
如果(结果)
{
var test=reader.GetString(0);
}
sqlConnection1.Close();
}
sw1.Stop();
Console.WriteLine(“完成:+sw1.Appeased”);
Console.WriteLine(“===Table2(1000)全文扫描===”;
var sw2=新秒表();
sw2.Start();
对于(int i=0;i<1000;i++)
{
cmd.CommandText=“从表2中选择名称,其中的名称类似“%”+i+“%””;
cmd.CommandType=CommandType.Text;
cmd.Connection=sqlConnection1;
sqlConnection1.Open();
reader=cmd.ExecuteReader();
var result=reader.Read();
如果(结果)
{
var test=reader.GetString(0);
}
sqlConnection1.Close();
}
sw2.Stop();
Console.WriteLine(“完成:+sw2.Appeased”);
Console.ReadKey();
为了模拟实体框架,我打开并关闭了每个查询的连接

中的应用程序安装在server1上,数据库位于数据库服务器上,当我运行此应用程序时,会得到以下结果:

我的计算机(同一系统上的应用程序+SQL Server):

  • 按键搜索:1m53s
  • 全文:4m31s
服务器1(通过网络的应用程序、数据库):

  • 键搜索:30m49s(!!!!)
  • 全文:9m19s
数据库服务器:

  • 按键搜索:7m07s
  • 全文:8m45s

区别似乎与网络有关,但服务器都只是位于同一硬件上的虚拟机。有没有人知道是什么原因导致应用服务器性能如此差

许多小手术显然比一些大手术更糟糕。对SQL Server运行的任何查询都会产生一些与网络相关的开销

我不熟悉VMs管理,但无论它们是否位于同一物理服务器上,都会有与TCP-IP通信相关的开销。快速查询将承受巨大的通信开销

一个有趣的测试是将查询分批进行。一种快捷方式(仅限语句构造):

const int batchSize=100;
对于(int j=0;j

另外,要知道是否使用连接池也是很重要的。如果您不使用它,那么在您的场景中关闭连接的成本非常高(打开连接、运行查询、关闭连接)。我注意到您的连接字符串,看起来您正在使用连接池(默认情况下处于活动状态)。

我不喜欢这一节:

为了模拟实体框架,我打开并关闭了每个查询的连接

创建和关闭连接是一个相当“昂贵”的过程,因此有一种软件设计模式。有关详细信息,请参阅文章

另外,不建议将load generator(在您的情况下是命令行应用程序)和SQL server实例放在同一台主机上,以避免在使用操作系统资源时相互干扰和冲突


我建议使用第三方工具,即提供执行负载的工具,这样您可以更清楚地了解查询响应时间,并能够将响应时间的增加与负载的增加联系起来。当您达到响应时间将超过可接受阈值(也称为“瓶颈”)的程度时,您将能够看到根本原因,并通过添加更多资源或修改SQL server连接配置或优化查询来解决它

如果您试图模拟EF,我建议使用参数化查询。这可能会稍微提高性能,但往返的次数将是帐篷中最长的一根柱子。FWIW,在一个1gb的网络上,通过一个普通硬件上的单线程应用程序,您应该能够每秒实现超过2K个琐碎的查询。这与您在db服务器上看到的本地内容有关,因此VM不是它可能的样子。因此,您演示了网络流量需要时间。这并不新鲜。其余的可能归因于命名管道协议与TCP/IP。
const int batchSize = 100;
for (int j = 0; j < batchSize; j ++)
{
    string inStr = string.Join("AND ", $"Name LIKE '%{i+j}%'");
    cmd.CommandText = $"SELECT Name FROM table2 WHERE 1 = 1 {inStr}";
}