1

ReadXml を介して XML ファイルからロードしている ADO DataSet があります。データとスキーマは別のファイルにあります。

現在、この DataSet をロードするのに 13 秒近くかかります。DataSet のスキーマを読み取らず、ReadXml にスキーマを推測させるだけで、これを 700 ミリ秒に短縮できますが、結果の DataSet には制約が含まれていません。

私はこれをやってみました:

Console.WriteLine("Reading dataset with external schema.");
ds.ReadXmlSchema(xsdPath);
Console.WriteLine("Reading the schema took {0} milliseconds.", sw.ElapsedMilliseconds);
foreach (DataTable dt in ds.Tables)
{
   dt.BeginLoadData();
}
ds.ReadXml(xmlPath);
Console.WriteLine("ReadXml completed after {0} milliseconds.", sw.ElapsedMilliseconds);
foreach (DataTable dt in ds.Tables)
{
   dt.EndLoadData();
}
Console.WriteLine("Process complete at {0} milliseconds.", sw.ElapsedMilliseconds);

これを行うと、スキーマの読み取りに 27 ミリ秒かかり、DataSet の読み取りに 12000 ミリ秒以上かかります。これは、すべての DataTable で EndLoadData を呼び出すに報告された時間です。

これは膨大な量のデータではありません。約 1.5 MB で、ネストされたリレーションはなく、すべてのテーブルには 6 ~ 30 文字の列が 2 つまたは 3 つ含まれています。スキーマを前もって読んだ場合に異なることがわかる唯一のことは、スキーマにはすべての一意の制約が含まれているということです。しかし、BeginLoadData は制約をオフにすることになっています (変更通知なども同様です)。したがって、ここでは当てはまりません。(はい、EnforceConstraints を false に設定してみました。)

オブジェクトにスキーマを推測させるのではなく、最初にスキーマを読み取ることで DataSet の読み込み時間を改善したという多くの報告を読みました。私の場合、スキーマを推測すると、スキーマを明示的に提供するよりも約 20 倍高速なプロセスが実現します。

これは私を少し夢中にさせています。この DataSet のスキーマは、メタ情報から生成されます。私は、それをプログラムで作成し、XmlReader で非シリアル化するだけのメソッドを書きたいと思っています。しかし、私はそうしないほうがいいです。

私は何が欠けていますか?ここで速度を向上させるために他に何ができますか?

4

3 に答える 3

1

テキストプレーンファイルとxmlファイルにデータを保存する場合のパフォーマンスの比較を試みます。

最初の関数は、プレーン テキストの 1000000 レコードを含む 1 つのファイルと、xml の 1000000 (同じデータ) レコードを含む 1 つのファイルの 2 つのファイルを作成します。まず、ファイル サイズの違いに注意する必要があります: ~64MB (プレーン テキスト) と ~102MB (xml ファイル)。

void create_files()
    {
        //create text file with data
        StreamWriter sr = new StreamWriter("plain_text.txt");

        for(int i=0;i<1000000;i++)
        {
            sr.WriteLine(i.ToString() + "<SEP>" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb" + i.ToString());
        }

        sr.Flush();
        sr.Close();

        //create xml file with data
        DataSet ds = new DataSet("DS1");

        DataTable dt = new DataTable("T1");

        DataColumn c1 = new DataColumn("c1", typeof(int));
        DataColumn c2 = new DataColumn("c2", typeof(string));

        dt.Columns.Add(c1);
        dt.Columns.Add(c2);

        ds.Tables.Add(dt);

        DataRow dr;

        for(int j=0; j< 1000000; j++)
        {
            dr = dt.NewRow();
            dr[0]=j;
            dr[1] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb" + j.ToString();
            dt.Rows.Add(dr);
        }

        ds.WriteXml("xml_text.xml");

    }

2 番目の関数は、これら 2 つのファイルを読み取ります。最初にプレーン テキストをディクショナリに読み取り (実際の使用をシミュレートするため)、その後 XML ファイルを読み取ります。どちらのステップもミリ秒単位で測定されます (結果はコンソールに書き込まれます)。

メモリへのテキスト ファイルの読み取りを開始
7628 ミリ秒でメモリにロードされたテキスト ファイルメモリ
への XML ファイルの読み取りを開始
21018 ミリ秒でメモリにロードされた XML ファイル

void read_files()
    {

        //timers
        Stopwatch stw = new Stopwatch();
        long milliseconds;

        //read text file in a dictionary

        Debug.WriteLine("Start read Text file into memory");

        stw.Start();
        milliseconds = 0;

        StreamReader sr = new StreamReader("plain_text.txt");
        Dictionary<int, string> dict = new Dictionary<int, string>(1000000);
        string line;
        string[] sep = new string[]{"<SEP>"};
        string [] arValues;
        while (sr.EndOfStream!=true) 
        {
            line = sr.ReadLine();
            arValues = line.Split(sep,StringSplitOptions.None);
            dict.Add(Convert.ToInt32(arValues[0]),arValues[1]);
        }

        stw.Stop();
        milliseconds = stw.ElapsedMilliseconds;

        Debug.WriteLine("Text file loaded into memory in " + milliseconds.ToString() + " milliseconds" );



        //create xml structure
        DataSet ds = new DataSet("DS1");

        DataTable dt = new DataTable("T1");

        DataColumn c1 = new DataColumn("c1", typeof(int));
        DataColumn c2 = new DataColumn("c2", typeof(string));

        dt.Columns.Add(c1);
        dt.Columns.Add(c2);

        ds.Tables.Add(dt);

        //read xml file

        Debug.WriteLine("Start read XML file into memory");

        stw.Restart();
        milliseconds = 0;

        ds.ReadXml("xml_text.xml");

        stw.Stop();
        milliseconds = stw.ElapsedMilliseconds;

        Debug.WriteLine("XML file loaded into memory in " + milliseconds.ToString() + " milliseconds");

    }

結論: XML ファイルのサイズは、テキスト ファイルのサイズのほぼ 2 倍であり、テキスト ファイルの 3 分の 1 の速度で読み込まれます。

XML の処理は (抽象化レベルのため) プレーン テキストよりも便利ですが、CPU/ディスクの消費量が多くなります。

したがって、ファイルが小さく、パフォーマンスの観点から許容できる場合は、XML データ セットで問題ありません。ただし、パフォーマンスが必要な場合は、XML データ セット (利用可能な任意の種類のメソッドを含む) がプレーン テキスト ファイルよりも高速かどうかはわかりません。基本的に、それは最初の理由から始まります。タグが多いため、XML ファイルが大きくなります。

于 2012-06-01T20:15:11.810 に答える
0

試行する別の次元は、スキーマなしでデータセットを読み取り、それを制約が有効になっている型指定されたデータセットにマージすることです。そうすれば、制約を適用するために使用されるインデックスを作成するときに、すべてのデータを手元に置くことができます。おそらく、より効率的でしょうか?

MSDNから:

通常、Merge メソッドは、変更の検証、エラーの調整、変更によるデータ ソースの更新、および最後に既存の DataSet の更新を含む一連の手順の最後に呼び出されます。

.

于 2009-02-25T04:06:05.960 に答える
0

正確には答えではありませんが (何もないよりはましですが、これは私がこれまでに得たものです)、この問題に長い間苦労した後、プログラムが Visual Studio 内で実行されていないときは完全に存在しないことがわかりました。

前に言及しなかったことで、これがさらに不可解になっているのは、別の (しかし比較的大きな) XML ドキュメントを DataSet にロードしたときに、プログラムが問題なく動作したことです。私の DataSets の 1 つに、Visual Studio が実行時にチェックしているメタ情報が添付されていて、他のメタ情報がチェックされていないかどうか疑問に思っています。私は知らないよ。

于 2008-12-03T02:39:09.170 に答える