【发布时间】:2014-12-31 21:50:28
【问题描述】:
一行 rdr.GetString 需要 12-15 秒
几行需要 4 - 5 秒
几个需要 1-4 秒
大多数行都小于 100 毫秒
整个查询仅返回 3286 行,在 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"));
}
【问题讨论】:
-
@Rhumborl 但它挂在 GetString 上——这怎么用词不当?如果我将 textValue 分配给硬编码的“值”,这没有问题
-
第一个查询是导致问题的原因吗?即
order by fieldID, rownum与desc添加到它?如果是这样,请尝试在子查询的order by子句中删除“ltrim(rtrim(..))”。 -
@shahkalpesh 没有解决问题。它现在挂在不同的行上。正如我所说,查询在 SSMS 中运行良好。它已经在该行上执行了 rdr.GetByte(0) 没有问题。
标签: .net sqldatareader