2012-01-27 13 views
1

SQLモニタリング製品で作業していますが、SQLのすべてのデータベースのすべてのテーブルの詳細に関するデータを取得するデータベースクエリがあります。サーバ。各データベースでクエリを実行する方法C#とSQL Serverでパフォーマンスの差を計算する方法

これには2つのオプションがあります。 select name from [master].sys.sysdatabases として、コードからのデータベース上

  1. 火クエリのすべてのデータベースのDB名が最初に、私は"USE <fetched DB name>;"+"mainQuery";

    を使用して、各DB 上の私のメインのクエリを起動します取得のためのfollowinコードをご確認ください同じ。

    public DataTable GetResultsOfAllDB(string query) 
    { 
        SqlConnection con = new SqlConnection(_ConnectionString); 
        string locleQuery = "select name from [master].sys.sysdatabases"; 
        DataTable dtResult = new DataTable("Result"); 
        SqlCommand cmdData = new SqlCommand(locleQuery, con); 
        cmdData.CommandTimeout = 0; 
    
        SqlDataAdapter adapter = new SqlDataAdapter(cmdData); 
        DataTable dtDataBases = new DataTable("DataBase"); 
        adapter.Fill(dtDataBases); 
    
        foreach (DataRow drDB in dtDataBases.Rows) 
        { 
         if (dtResult.Rows.Count >= 15000) 
          break; 
         locleQuery = " Use [" + Convert.ToString(drDB[0]) + "]; " + query; 
         cmdData = new SqlCommand(locleQuery, con); 
         adapter = new SqlDataAdapter(cmdData); 
         DataTable dtTemp = new DataTable(); 
         adapter.Fill(dtTemp); 
         dtResult.Merge(dtTemp); 
        } 
        return dtResult; 
    } 
    
  2. IはTEMPTABLEから選択テーブルデータ型に格納するデータを格納されるSYSストア手順i.e.EXEC sp_MSforeachdbとフェッチされたデータを使用します。ドロップテーブルは魅力的です。

    Declare @TableDetail table ( field1 varchar(500), field2 int, field3 varchar(500), field4 varchar(500), field5 decimal(18,2), field6 decimal(18,2) ) INSERT @TableDetail EXEC sp_MSforeachdb 'USE [?]; QYERY/COMMAND FOR ALL DATABASE' Select field1,field2 ,field3 ,field4 ,field5,field6 FROM @TableDetail

注同じ

ため 確認し、次のクエリ:データベースとテーブルの数の数が膨大であれば、これは仕上げを取得するすべてのデータベースまで、お待ちしておりますので、2番目のオプションのクエリでは、時間がかかります。

私の質問は、上記の2つのオプションのどちらが良い選択肢ですか、なぜですか?または同じもののための他の任意の解決策。

ありがとうございます。

+0

はどのようにして、各テストの間のシステムの違いやネットワーク遅延を決定しようとしているオブジェクト、これは最終的には何の関係もありません定義する要因となる可能性1つのDBパフォーマンス。 – Lloyd

+0

私は心配です、それぞれのDBとフェッチデータまたは毎回1つの接続を開いて接続するたびに巨大なクエリを実行するのは大丈夫ですか? N/Wレイテンシに関してはこれは正しいですが、これはDBのパフォーマンスとは関係ありませんが、各DBまたはOlyのconnectopnの接続を再オープンする方が良いです – Darshan

+0

ここで何をしたのですか? – bryanmac

答えて

1

重要な違いの1つは、すべてが完了するまで2番目のオプションブロックです。すべての作業はSQL Server側で行われます。これは、実行中にユーザーにフィードバックを与えることができないという問題を抱えています。タイムアウトになる可能性があり、ネットワーク・ブリップに耐えられない可能性があります。このオプションは、最初のプログラムが必要な純粋なSQLスクリプト(そのようなSQL管理者の一部)として使用できます。

最初の例では、クライアントはユーザーにフィードバックを提供できる反復的な細かいタスクを実行しています。すべての作業をやり直すことなく、ネットワークブリップに直面して再試行することもできます。最初の例では、USE連結の代わりにSqlConnectionBuildを使用することもできます。

パフォーマンスが懸念される場合は、潜在的にadapter.Fill

1

両方の周りにいくつかのロックで最初のものを並列化することができ吸う - 彼らは両方のシリアルです。

最初のものを使用してばかげたオブジェクト(DataSet)を取り除き、TASKSを使用してXデータベースを同時に並列化します。 Xは、サーバーが処理できる負荷を試して決定します。

仕上げ。

+0

はい、あなたは正しいですが、問題は私のアプリが2.0で、2.0での並列処理を扱いにくいことです。私はThreadingを適用しなければなりません。そして、私はこの製品がMonitoring製品であるため、これをやりたいとは思っていません。私はこのようなことをするつもりはありません。 – Darshan

+0

ああ、申し訳ありません。 ThreadPoolを使用して、ユーザーの作業項目をキューに入れます。私は1.0からそれをやっている。それに問題はない。 – TomTom

0

クエリが十分なあなたは、単一のスクリプトを生成する代わりに、のいずれかによって、各DB 1でクエリを実行しようとすることができるシンプルある場合:

select 'DB1' as DB, Field1, Field2, ... 
from [DB1]..[TableOrViewName] 
union all 
select 'DB2' as DB, Field1, Field2, ... 
from [DB2]..[TableOrViewName] 
union all 
... 
0

すべてが正常探しています。私はちょうどIDisposableをのための文を使用してを追加したい

public DataTable GetResultsOfAllDB(string query) 
     { 
      using (SqlConnection con = new SqlConnection(_ConnectionString)) 
      { 
       string locleQuery = "select name from [master].sys.sysdatabases"; 
       DataTable dtResult = new DataTable("Result"); 
       using (SqlCommand cmdData = new SqlCommand(locleQuery, con)) 
       { 
        cmdData.CommandTimeout = 0; 

        using (SqlDataAdapter adapter = new SqlDataAdapter(cmdData)) 
        { 

         using (DataTable dtDataBases = new DataTable("DataBase")) 
         { 
          adapter.Fill(dtDataBases); 

          foreach (DataRow drDB in dtDataBases.Rows) 
          { 
           if (dtResult.Rows.Count >= 15000) 
            break; 
           locleQuery = " Use [" + Convert.ToString(drDB[0]) + "]; " + query; 
           cmdData = new SqlCommand(locleQuery, con); 
           adapter = new SqlDataAdapter(cmdData); 
           using (DataTable dtTemp = new DataTable()) 
           { 
            adapter.Fill(dtTemp); 
            dtResult.Merge(dtTemp); 
           } 
          } 
          return dtResult; 
         } 
        } 
       } 
      } 
     }