DataTable.Load 比 IDataAdapter.Fill 更慢?

3
我正在使用以下代码(Variant DataReader):
public DataTable dtFromDataReader(list<String> lstStrings)
{

    OleDBConn_.Open();
    using (OleDbCommand cmd = new OleDbCommand())
    {

        DataTable dt = new DataTable();
        OleDbDataReader reader = null;
        cmd.Connection = OleDBConn_;
        cmd.CommandText = "SELECT * from TableX where SUID=?";

        foreach (String aString in lstStrings)
        {
            cmd.Parameters.AddWithValue("?", aNode.SUID);
            reader = cmd.ExecuteReader();

            if (reader != null)
                dt.Load(reader);
            cmd.Parameters.Clear();
        }
        return dt;
    }
}

并将其与(变体DataAdapter)进行比较:

public DataTable dtFromDataAdapter(list<String> lstStrings)
{
    dt = new DataTable();

    foreach (string aString in lstStrings)
    {
        sOledb_statement = String.Concat("SELECT * FROM TableX where SUID='", aString, "'");
        OleDbDataAdapter oleDbAdapter;
        using (oleDbAdapter = new OleDbDataAdapter(sOledb_statement, OleDBConn_))
        {
            GetOleDbRows = oleDbAdapter.Fill(dt);
        }
    }
}

当我连接到离线数据库(Microsoft Access)时,我的读取时间为(检索1.5k个项目):
- DataReader 420毫秒 - DataAdapter 5613毫秒
当从Oracle服务器中读取(检索30k个项目):
- DataReader 323845毫秒 - DataAdapter 204153毫秒(多次测试,时间变化不大)
即使更改命令的顺序(DataAdapter在DataReader之前),也没有太大变化(我认为可能有一些预缓存...)。
我认为DataTable.Load应该比DataAdapter.Fill快一些?
尽管我看到了结果,但我仍然相信它应该更快。我在哪里浪费时间?(没有未处理的异常...)

2
你在哪里进行计时?其中一种方法中有连接Open()调用,另一种方法没有。那可能就是差异的一部分。 - Ben Lesh
另外,一个示例使用参数,而另一个则没有。在一种情况下,您只读取单行,但 DataAdapter.Fill 会读取所有行。 - John Saunders
@blesh 适配器在fill方法中处理连接的打开和关闭。 - LarsTech
有趣,我不知道那个。 - Ben Lesh
@JohnSaunders 我刚测试了一下,dt.load() 已经按照预期加载了结果 - 所以也保存了几行。 - jaufer.k
有可能是因为SQL保存了该查询的查询计划,所以第二次调用更快吗? - Ben Lesh
1个回答

2

您的比较并不是适配器(Adapter)与DataReader之间的比较,因为您的代码设置方式不同。实际上,您正在比较Adapter.Fill和DataTable.Load方法。

通常情况下,DataReader在每个记录上的速度会更快,因为您将一次遍历一个记录,并且可以在读取每个记录时做出相应的反应。

由于您在两种情况下都返回了一个DataTable,因此Adapter.Fill方法可能是最佳选择。它就是为这个目的而设计的。


它们两个都在DataAdapter中内部调用了protected virtual int Fill(DataTable[] dataTables, IDataReader dataReader, int startRecord, int maxRecords)方法。我不确定这是否是答案。 - Ben Lesh
(我也不确定,但这可能不是答案) - Ben Lesh
既然你告诉我我在那里做了什么,我现在明白我在那里做了什么。谢谢! - jaufer.k
我认为你在添加和删除参数上浪费了时间。如果你只添加一次参数,然后在循环内部改变它的值,这会更快。如果你注意到在适配器选择语句中没有使用参数,那么这个比较是不正确的。此外,你不必检查读取器是否有数据。 - Shehab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接