2

現在、SQL Serverを基盤とするデータベースを使用している.netコアで構築されたアプリケーションのパフォーマンスに関する問題をデバッグしています。 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(); 

Entity Frameworkのをシミュレートするために私が開かれ、各クエリの接続を閉じました。

私は、このアプリケーションを実行すると、私は次のような結果を得る、server1上のインストール、およびデータベースは、データベース・サーバー上に配置されているでアプリケーション:

私のマシン(同じシステム上のアプリ+ SQL Serverの):

  • キーシーク:1m53s
  • 全文:4m31s

のServer1(アプリ、ネットワークを介したデシベル):

  • キーシーク:30m49s(!!!!)
  • 全文:9m19s

データベースサーバー:

  • キーシーク:7分7秒
  • 全文:8m45s

違いはネットワーク関連のようですが、サーバーはすべてVMが同じハードウェア上に座っているだけです。誰かがアイデアを持っていますが、このパフォーマンスの低下をアプリサーバーに引き起こす原因は何ですか?

+0

EFをシミュレートする場合は、パラメータ化されたクエリを使用することをお勧めします。それは少しパフォーマンスを改善するかもしれませんが、ラウンドトリップの数はテントの長いポールになります。 FWIWでは、一般的なハードウェア上でシングルスレッドのアプリケーションを使用して1Gbのネットワーク上で1秒あたり2Kを超える些細なクエリを達成できるはずです。それはあなたがdbサーバ上でローカルに見ているもので、VMはそれができるものではありません。 –

+0

あなたは、ネットワークトラフィックに時間がかかることを実証しました。それは新しいことではない。残りの部分は、名前付きパイププロトコルとTCP/IPの関係にあると考えられます。 –

答えて

0

私はこのスタンザが好きではない:

Entity Frameworkのをシミュレートするために、私は開かれ、各クエリの接続を閉じました。

接続の作成と終了は非常に「コストがかかる」プロセスなので、Connection poolソフトウェア設計パターンがあります。詳細については、Using Connection Pooling with SQL Serverの記事を参照してください。

また、オペレーティングシステムのリソースを使用する際に相互干渉や干渉を避けるために、ロードジェネレータ(お使いの場合はコマンドラインアプリケーション)とSQL Serverインスタンスを同じホストに置くことはお勧めしません。

サードパーティ製のツールApache JMeterを使用することをお勧めします。この方法では、クエリの応答時間をより明確に把握し、増加する応答時間と増加する負荷を関連付けることができます。JDBC Request sampler応答時間が許容可能なしきい値(「ボトルネック」とも呼ばれます)を超えるようになると、根本的な理由を確認し、リソースを追加したり、SQLサーバー接続構成を変更したり、クエリを最適化したりできます。

0

多くの小規模な操作は、いくつかの大きな操作より明らかに悪いです。 SQL Serverに対して実行するクエリには、ネットワーク関連のオーバーヘッドがあります。

私は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}"; 
} 

また、重要なことは知っています。あなたがそれを使用しない場合、あなたのシナリオでは接続を閉じることは本当に高価です(接続を開く、クエリを実行する、閉じる)。接続文字列に気付きました。接続プール(デフォルトではアクティブ)を使用しているように見えます。

関連する問題