首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同时使用多个ExecuteReader

同时使用多个ExecuteReader
EN

Stack Overflow用户
提问于 2012-04-19 11:03:40
回答 5查看 2.3K关注 0票数 0

我正在读取一个使用ExecuteReader()命令包含一些表的db。根据第一个Read()结果的结果,我读取了两个不同的表,因为我需要在第一个查询上返回ID来运行第二个查询。

问题是这个搜索过程非常缓慢。

代码语言:javascript
复制
tuCommand.CommandText = "SELECT * FROM tblTranslationUnit WHERE DocumentId = " + doc.DocumentId;
var tuReader = tuCommand.ExecuteReader();
while (tuReader.Read())
{
    var tu = new TranslationUnit
     {
         TranslationUnitId = tuReader.GetInt64(0),
         DocumentId = tuReader.GetInt64(1),
         Raw = tuReader.GetString(2),
         IsSegmented = tuReader.GetBoolean(3),
         Reader = this, // Ryan: Fixed so that it sets the reader to itself
     };

    using (var propCommand = _dbConn.CreateCommand())
    {
        propCommand.CommandText = "SELECT * FROM tblTranslationUnitProperties WHERE TranslationUnitId = " + tu.TranslationUnitId;
        var propReader = propCommand.ExecuteReader();
        while (propReader.Read()) tu.Properties.Add(GetProperty(propReader));
    }
    yield return tu;
}

如果删除第二个ExecuteReader(),查询非常快

我还尝试使用新连接和新事务放置第二个ExecuteReader(),但结果几乎相同

有什么想法或线索吗?我怎样才能进行这种搜索呢?有没有更好的方法?(我想是的)

有关db结构的更多细节如下:

代码语言:javascript
复制
  - Document
      - properties
      - errors
    -TranslationUnits
        - properties
        - errors
      - Segments
          - properties
          - errors

因此,在代码的某些部分中,我们将有这样的结构

代码语言:javascript
复制
  foreach (document in db)
      foreach (property in document)
      foreach (error in document)
    foreach (translationunit in document)
        foreach (property in translationunit)
        foreach (error in translationunit)
      foreach (segment in translationunit)
          foreach (property in segment)
          foreach (error in segment)

基于此,使用join返回所有内容不是一个好主意--如果问题只是SQLite配置问题的话。我的意思是,如果可以添加任何参数或类似的参数来告诉系统,我们将使用几个指针

现在,我们将转移到datatable解决方案:

打开connection

  • read 1000条目的表

  • 关闭connection

  • open新的connection

  • read 1000条目的子表

  • 关闭新的connection

  • ...
EN

回答 5

Stack Overflow用户

发布于 2012-04-19 11:21:49

听起来好像您有可伸缩性问题。SQLite有"Lite“这个词是有原因的。它缺乏某些东西,比如高并发性、细粒度的访问控制、丰富的内置函数集、存储过程、深奥的SQL语言特性、XML和/或Java扩展、tera或peta字节可伸缩性等等。我建议为初学者更改数据库。

我也不清楚你的问题,为什么你需要在内存中同时有1000个文档,尤其是1000个文件,1000个部分,多1000个部分,全部存储在内存中。我不知道您的UI需求,但在编程的15+年中,我不记得在没有某种分页机制的情况下,必须在单个网页或表单上显示1000个实体,那么您真的需要同时从数据库中获取1000个* 1000 *1000个实体吗?

我认为您需要重新审视UI、当前模型和数据层,寻找在不牺牲大量性能的情况下提供尽可能少的内容的方法。考虑使用诸如延迟加载、提前读取缓冲区、缓存、分页、搜索方法、共享静态数据等模式来降低前期成本。

从买房的角度考虑。我们中的大多数人都没有足够的钱来预付房贷,所以我们得到了抵押贷款。抵押贷款是一种在一段时间内分摊前期成本的方法。所有被称为利息的抵押贷款都会带来负面影响。现在,我没有花100,000,我的总成本变成了250,000,但因为我能够支付现在的费用,我没有真正注意到额外的15万,因为额外的成本会随着时间的推移以小幅度的增加而被吸收。还要注意的是,如果我在5年内卖掉我的房子,而不是一辈子的贷款,我甚至可能还不了250,000美元。

这里的要点是,您可以分摊建立额外连接以检索较小记录集的成本,并且仍然可以为用户提供他们现在需要的东西。这将降低整体的前期成本,但将增加一个额外的成本的各个记录集被检索。

票数 1
EN

Stack Overflow用户

发布于 2012-04-21 22:37:19

嗨,我要在这上面加上我的发现(我和大卫一起醒来)

我修改了使用david描述的缓冲区从db读取表的方式,这样既没有同时连接,也没有同时执行的读取器。它看起来有点快,但非常引人注目。这里有一些数字。

我在2.5秒内用5000个翻译单位填充数据库(所有表)。然后,当我循环遍历TranslationUnit表(大约5000行)时,读取的时间是惊人的:0.07秒。代码看起来如下:

代码语言:javascript
复制
foreach (var tu in document)
{
   ... do something ...
}

如果我像这样阅读每个翻译单元的片段:

代码语言:javascript
复制
foreach (var tu in document)
{
    foreach (var seg in tu)
    {
        ... do something ...
    }
}

阅读时间开始变得丑陋:大约10秒。注意,每个翻译单元都有两个片段(尽管我们在设计中没有限制这一点)

对于10000个翻译单位,填充数据库大约需要6秒,读取数据库需要大约2分钟。(如果只读一遍翻译单元,几乎是即时的)

对于50000个翻译单位,填充大约需要32秒钟,在等待阅读完成1小时之后,我放弃了。(如果只读一遍翻译单元,几乎是即时的)

所以我猜阅读时间成本是成倍增长的。是否有理由认为这是因为它必须将数据库指针更改为不同的表?(翻译单位与段表之间)。

票数 1
EN

Stack Overflow用户

发布于 2012-04-19 11:09:59

你试过简单的“加入”吗?还是我在你的问题上遗漏了什么?

代码语言:javascript
复制
SELECT tbl2.* 
    FROM tblTranslationUnit tbl1 
    JOIN tblTranslationUnitProperties tbl2 ON tbl2.TranslationUnitId = tbl1.TranslationUnitId 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10226666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档