XML解析速度慢,还是SQL插入方法的瓶颈?

时间:2013-05-24 21:44:56

标签: xml csv xml-parsing sql-server-ce database-performance

虽然我认为这可能是导致问题的数据量,而不是我们发送/解析它的方式(以及接收数据的设备是98磅的弱点(旧手持设备)使用.NET 1.1)运行Windows CE的设备,我的任务是更改某些数据的XML处理,以解析将替代它们的CSV文件。

“有问题的”数据是典型的XML票价:

<PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>010476</PlatypusItemID>
    <ItemID>01820000468</ItemID>
    <BillSize>15</BillSize>
  </PlatypusItems>
  <PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>011065</PlatypusItemID>
    <ItemID>01820000478</ItemID>
    <BillSize>15</BillSize>
  </PlatypusItems>
  <PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>015165</PlatypusItemID>
    <ItemID>01820000481</ItemID>
    <BillSize>15</BillSize>
  </PlatypusItems>
  <PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>010420</PlatypusItemID>
    <ItemID>01820000907</ItemID>
    <BillSize>24</BillSize>
  </PlatypusItems>
(etc.)

在查看(传统 - 我没有编写)代码时,我看到一些看起来很奇怪的东西(至少对我而言),并想知道它们是否可能,而不是数据大小或解析方法,至少是问题的一部分。

例如,有没有理由在下面的第二个实例中使用var dSQL?它与SqlCeCommand的CommandText属性相同,但不使用params。把它放在上下文中,我会展示一些代码:

if (File.Exists(filePathName)) // <-- filePathName contains the name of the XML file to be parsed
{
    DataSet dset = new DataSet("DuckbillSetup");
    dset.ReadXml(filePathName);

    dSQL = "DELETE FROM Platypi";
    try
    {
        dbconn.DBCommand(dSQL, true);
    }
    catch
    {
        //bla [elided/excised]
    }

    SqlCeConnection conn = dbconn.GetConnection();
    if (conn != null && conn.State == ConnectionState.Closed)
    {
        conn.Open();
    }
    SqlCeCommand cmd = conn.CreateCommand();

    cmd.CommandText = "INSERT INTO Platypi ( PlatypusID, PlatypusItemID, ItemID, BillSize) VALUES (?, ?, ?, ?)";

    foreach (DataTable tab in dset.Tables)
    {
        if (tab.TableName.ToLower() == "Platypi".ToLower())
        {
            foreach (DataRow row in tab.Rows)
            {
                PlatypusItem PlatypusItm = new PlatypusItem();
                if (!ret)
                    ret = true;
                foreach (DataColumn column in tab.Columns)
                {
                    if (column.ColumnName == "PlatypusID")
                    {
                        PlatypusItm.PlatypusID = (string) row[column];
                    }
                    else if (column.ColumnName == "PlatypusItemID")
                    {
                        if (!row.IsNull(column))
                            PlatypusItm.PlatypusItemID = (string) row[column];
                        else
                            PlatypusItm.PlatypusItemID = "";
                    }
                    else if (column.ColumnName == "ItemID")
                    {
                        if (!row.IsNull(column))
                            PlatypusItm.ItemID = (string) row[column];
                        else
                            PlatypusItm.ItemID = "";
                    }
                    else if (column.ColumnName == "BillSize")
                    {
                        if (!row.IsNull(column))
                            PlatypusItm.BillSize = Convert.ToInt32((string) row[column]);
                        else
                            PlatypusItm.BillSize = 0;
                    }
                }
                PlatypusItemList.List.Add(PlatypusItm);

                dSQL = "INSERT INTO Platypi (PlatypusID, PlatypusItemID, ItemID, BillSize) VALUES (" + PlatypusItm.PlatypusID + ",'" +
                       PlatypusItm.PlatypusItemID + "','" + PlatypusItm.ItemID + "'," + PlatypusItm.BillSize + ")";

                if (!First)
                {
                    cmd.Parameters[0].Value = PlatypusItm.PlatypusID;
                    cmd.Parameters[1].Value = PlatypusItm.PlatypusItemID;
                    cmd.Parameters[2].Value = PlatypusItm.ItemID;
                    cmd.Parameters[3].Value = PlatypusItm.BillSize.ToString();
                }

                if (First)
                {
                    cmd.Parameters.Add("@PlatypusID", PlatypusItm.PlatypusID);
                    cmd.Parameters.Add("@PlatypusItemID", PlatypusItm.PlatypusItemID);
                    cmd.Parameters.Add("@ItemID", PlatypusItm.ItemID);
                    cmd.Parameters.Add("@BillSize", PlatypusItm.BillSize);
                    cmd.Prepare();
                    First = false;
                }

                if (frmCentral.CancelFetchInvDataInProgress)
                {
                    return false;
                }

                try
                {
                    dbconn.DBCommand(cmd, dSQL, true); // <-- Why dSQL? Why not: dbconn.DBCommand(cmd, cmd.CommandText, true);
                }
            . . .

...我倾向于认为问题更可能是在命令中使用dSQL(因此不是解析XML就是问题,而是插入到数据库中,这可能是“hicc [ough] ,“每次它在SQL语句中面对那些必须解开的类成员,而不是让params飞过来”。如果 的情况是XML解析的性能远低于CSV解析,那么有没有办法加快速度,或者切换到CSV文件真的很合理?

更新

我刚刚通过将MessageBox.Show()s放在代码中进行测试(我必须这样做 - 长篇故事已经在这些区域中被困扰了很多次),就在解析/读取XML文件之前和之后,以及插入数据的for循环之前和之后。不可否认,我的测试数据并不是很大,但在这两种情况下,“开始”和“完成”消息之间的时间几乎是瞬间完成的......好奇的是人们会慢下来爬行(测试人员表示需要花费10分钟要加载的网站,他推断,另一个网站需要30分钟(不等待它)。

更新2

我不知道如何应用下面摘录的代码http://msdn.microsoft.com/en-us/library/537kf788(v=vs.90).aspx(链接到ErikEJ的答案):

cmd.CommandText = "SELECT * FROM myTable";
SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable |
    ResultSetOptions.Scrollable);

SqlCeUpdatableRecord rec = rs.CreateRecord();

// Insert 10 records
//
for (int i = 0; i < 10; i++)
{
    rec.SetInt32(0, i);
    rs.Insert(rec);
}

首先从表格中读取所有记录真的有必要/明智吗?如果它有很多记录呢?或者它实际上没有这样做?

SetInt32()做什么?看起来它可能假设表有一个正在更新的ID列,但这不可能,因为通常那些会自动化,所以...... ???

也许 rec.SetInt32(0,i)只是一个占位符:

rec.MyFirstClassmember(bla);
rec.MySecondClassmember(Blee);
...etc.

但无论如何,“SqlCeResultSet”和“SqlCeUpdatableRecord”似乎都不可用 - 事实上,使用此代码:

SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable | ResultSetOptions.Scrollable);
SqlCeUpdatableRecord rec = rs.CreateRecord();

...... VS2003代码编辑器中的所有内容都是红色的,除了“res = cmd。”,“。Updatable |”,“。Scrollable”和“rec = rs。”

没有“Resolve”上下文菜单项可用;我确实“使用System.Data.SqlServerCe;”在这个单位。

简而言之,这个应用程序的问题在于它像一个老式的迷幻屏幕保护程序一样在其周围编织; “意大利面条”这个词肯定会浮现在脑海中,并且适合,但也许更好的术语是“蛋壳”(想想Humpty Dumpty)。这可能是一个很大的难题:“意大利面什么时候变成蛋壳?”答:“当编写错误的代码时。”

更新3

在下面评论中提供的链接(http://mobilesandbox.blogspot.dk/2009/02/sql-compact-insert-performance.html)中的项目代码中:

rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable);
rec = rs.CreateRecord();

for(i = 0; i < m_nSampleSize; ++i) 
{
    rec.SetInt32(0, i);
    rs.Insert(rec);
}

......似乎一遍又一遍地插入相同的记录(rec)。我错了吗? rs是否足够聪明,每次都知道增加到结果集中的下一条记录?如果是这样,为什么它不仅仅是一个“而不是endOfResultSet”循环?

1 个答案:

答案 0 :(得分:1)

INSERT语句肯定会导致响应缓慢。有一些方法可以避免T-SQL并使用SQL Server Compact直接对“原始”表进行INSERT,在MSDN上查找SqlCeUpdateableRecord和SqlCeResultSet.Insert方法。 http://msdn.microsoft.com/en-us/library/537kf788(v=vs.90).aspx