慢SQLDataReader GetString

时间:2014-12-31 21:50:29

标签: .net sqldatareader

在一行rdr.GetString需要12-15秒

几行需要4-5秒 一些需要1-4秒
大多数行都小于100毫秒

整个查询只返回3,286行,并在SSMS中运行15秒

[Value]是varchar(600) - 我所知道的没什么特别的 [fieldID],[value]上有一个重建(多次)的索引

在SqlDataReader中,读取行208需要12 - 15秒
读取一行只需读取所有剩余的3,285行

如果我将[fieldID]上的排序更改为desc,则它会挂起第2050行 这不是同一行(它甚至不是相同的[fieldID])

在rdr.GetString是rdr.GetByte之前,它永远不会挂起在GetByte上。 它已经排了! 即使点击另一台具有相似但不完全正确的数据库的服务器,它也会挂起。

我知道这听起来很疯狂,但它正在发生。 感觉就像SqlDataReader挂起但我在这个应用程序中一直使用SqlDataReader并返回比这更多的行。

如果我在fieldID更改时执行手动GC.Collect(),它仍会挂在大多数相同的行上。 个人挂起的时间稍微小一些,但总数大致相同。使用1秒的阈值可能只有一个刚刚进入或刚出来,但问题行肯定会重复。

认为它可能与挂起之间的字符数有关,但可以低至600,高达60,000。

但它确实与返回的数据有关。 如果我排除或包含[rownumber](并且不读它),它将挂在不同的行上。 但行在同一个附近。

 fieldID = rdr.GetByte(0);    // this line does not hang
 delta = sw.ElapsedMilliseconds;
 textValue = rdr.GetString(1);  // this is the line that hang on some rows 
 if ((sw.ElapsedMilliseconds - delta) > 1000L)
    Debug.WriteLine("GabeLib_Helper sw in  fields  thisFieldID = " + thisFieldID + " counter = " + counter + " ccount = " + ccount + " after getstring read delta = " + (sw.ElapsedMilliseconds - delta).ToString("N0") + " textValue = " + textValue);

select [fieldID], [value], [rowNum]
from 
(
SELECT [fieldID], ltrim(rtrim([value])) as [value]
     , ROW_NUMBER() over ( partition by [fieldID] order by ltrim(rtrim([value])) ) as [rowNum]
  FROM [docSVtext] with (nolock)
  JOIN [docFieldDef] with (nolock)
    ON [docFieldDef].[ID] = [fieldID] 
   AND [docFieldDef].[typeID] in (101) 
   AND [docFieldDef].[active] =  'true' 
   AND len(ltrim(rtrim([value]))) > 0 and len(ltrim(rtrim([value]))) <= 200 
  JOIN [docSVsys] with (nolock) 
    on [docSVsys].[sID] = [docSVtext].[sID] 
   and [docSVsys].[visibility] = 0 
 group by [fieldID], ltrim(rtrim([value]))
 ) as withRow
 where [rowNum] < 1001
 order by [fieldID], [rowNum]

如果我添加rdr.GetInt64(2);在rdr.GetString(1)之上;
然后它挂在rdr.GetInt64(2);并且不会挂起rdr.GetString(1);
并使用rdr.GetInt64(2);我得到一个慢rdr.Read()。

delta = sw.ElapsedMilliseconds; 
rowNum = rdr.GetInt64(2);
if ((sw.ElapsedMilliseconds - delta) > 1000L)
    Debug.WriteLine("GabeLib_Helper sw in  fields  in PastEntries new rowNum  rdr.GetInt64(2) " + rowNum + " counter = " + counter + " ccount = " + ccount + "  delta = " + (sw.ElapsedMilliseconds - delta).ToString("N0"));

下面的查询在SSMS中在2秒内运行 这不是问题查询
包括显示索引似乎正在工作

  select fieldID, value, count(*)  
  from docSVtext 
  group by fieldID, value

我跟踪了GC并且它与慢速下降无关 即使GC运行它只需要20毫秒

delta = sw.ElapsedMilliseconds;
List<int> gcCounts = new List<int>();
for (int g = 0; g <= GC.MaxGeneration; g++) gcCounts.Add(GC.CollectionCount(g));
textValue = rdr.GetString(1);  //  " Chen, Andy </O=ENRON/OU=NA/CN=RECIPIENTS/CN=ACHEN>" + Guid.NewGuid(); //
if ((sw.ElapsedMilliseconds - delta) > 100L)
{
    Debug.WriteLine("GabeLib_Helper sw in  fields  thisFieldID = " + thisFieldID + " counter = " + counter + " ccount = " + ccount + " after getstring read delta = " + (sw.ElapsedMilliseconds - delta).ToString("N0") + " textValue = " + textValue);

}
for (int g = 0; g <= GC.MaxGeneration; g++)
{
    if (GC.CollectionCount(g) != gcCounts[g])
        Debug.WriteLine("GabeLib_Helper GC new count = " + GC.CollectionCount(g) + " old count =" + gcCounts[g] + " generation " + g + " ccount = " + ccount + " after getstring read delta = " + (sw.ElapsedMilliseconds - delta).ToString("N0"));
}

1 个答案:

答案 0 :(得分:0)

我想我想出来了

如果我删除

where [rowNum] < 1001

然后是没有任何长行读取
查询需要更长时间,因为它现在读取每一行
那个悬挂是它跳过这些行的时候 由于实际读者领先于阅读,因此很难看出

但SSMS中的问题仍然让我困惑

尝试了

select ID, count(*) 
  from table 
  ...
group by ID 
having count(*) > x

仅查询x计数下的ID 问题是查询需要几秒钟才能运行

我最终做的是

select top (x + 1), value 
  from table 
 where ID = i1
 group by value;
select top (x + 1), value 
  from table 
 where ID = i2
 group by value;
...

如果计数达到x + 1那么我就不用了它

发生的事情是一些非常重要的事情,在那里吃了很多时间,我甚至都不想要那些。即使得到大数的计数也很昂贵