作为标题,我遇到了与从MS-SQL读取数据有关的问题。 我使用DataReader编写了C#代码,用于检索查询返回的数据并将数据保存到CVS。非常简单,我很确定这段代码没有问题。
我有两个查询。第一个查询是内部联接4表的结果。 第二个查询在选择语句中使用Row_Num和子查询。它们全部返回24列。 第一个查询返回321k条记录。第二个查询返回2300条记录。 我正在使用SQL Server 2008。
问题是当我运行第一个查询时,它运行速度很快。 321k条记录保存到CVS文件,需要8分钟才能完成。但是,使用第二个查询,需要花费26个小时将2300条记录保存到文件中。我输入了登录代码,发现一些记录需要40到50分钟才能读取数据,我不知道为什么。
请看看并给我一些建议。
贝洛是我的代码,也是我所做的
using (var connection = new SqlConnection(connectionstring))
using (var command = new SqlCommand(secondQuery, connection))
{
connection.Open();
try
{
command.CommandTimeout = 0;
command.CommandType = CommandType.Text;
var reader = command.ExecuteReader();
using (var memoryStream = ExtendedStream.CreateMemoryStream())
using (TextWriter writer = new StreamWriter(memoryStream, Encoding.UTF8, 65536)) {
while (reader.Read())
{
// using Nlog to log start time begin read data and log what happen on code
// read property value and save to file
// using Nlog to log end time read data
}
}
reader.Dispose();
reader.Close();
}
catch (SqlException ex)
{
throw ex;
}
finally
{
command.Dispose();
connection.Dispose();
connection.Close();
}
}
第二个查询
WITH TEMP AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY SId,PointID ORDER BY UTCSysTime) Record_No, * FROM
(SELECT
*
FROM
Table_A WITH (NOLOCK)
WHERE
StatusID IN (1, 2)
AND [UTCSysTime] >= @StartTime
AND [UTCSysTime] <= @EndTime
UNION
SELECT
E.*
FROM
Table_A E WITH (NOLOCK)
INNER JOIN (SELECT
SId,
PointID,
StatusID,
UTCSysTime = MIN(UTCSysTime)
FROM
Table_A WITH (NOLOCK)
WHERE
StatusID IN (1, 2)
AND [UTCSysTime] > @EndTime
GROUP BY
SId,
PointID,
StatusID
) E2
ON E.SId = E2.SId
AND E.PointID = E2.PointID
AND E.StatusID = E2.StatusID
AND E.UTCSysTime = E2.UTCSysTime
) T
)
SELECT
*,
[PointShortName] = CONVERT(VARCHAR(255), (SELECT TOP 1
ShortName
FROM
Table_B _T
WITH (NOLOCK)
WHERE
_T.PointID = Table_T.PointID
)),
[Description_Point] = CONVERT(VARCHAR(2000), (SELECT TOP 1
_T.Name
FROM
Table_Point _T
WITH (NOLOCK)
WHERE
_T.PointID = Table_T.PointID
AND _T.DescID = 1
)),
[Description_1] = CONVERT(VARCHAR(255), (SELECT TOP 1
Name
FROM
Table_C
WITH (NOLOCK)
WHERE
DescID = 1
AND CatID = [Table_T].[Cat1]
)),
[Description_2] = CONVERT(VARCHAR(255), (SELECT TOP 1
Name
FROM
Table_C
WITH (NOLOCK)
WHERE
DescID = 1
AND CatID = [Table_T].[Cat2]
)),
[Description_3] = CONVERT(VARCHAR(255), (SELECT TOP 1
Name
FROM
Table_C
WITH (NOLOCK)
WHERE
DescID = 1
AND CatID = [Table_T].[Cat3]
)),
[Description_4] = CONVERT(VARCHAR(255), (SELECT TOP 1
Name
FROM
Table_C
WITH (NOLOCK)
WHERE
DescID = 1
AND CatID = [Table_T].[Cat4]
))
FROM
(SELECT
*
FROM
(SELECT
a.*
,UTCSysTime_End = ISNULL(CASE WHEN b.StatusID = 1
THEN b.UTCSysTime
END,
CASE WHEN c.StatusID = 1
THEN c.UTCSysTime
END)
FROM TEMP a LEFT OUTER JOIN TEMP b ON a.Record_no = b.Record_no - 1 and a.SId = b.SId and a.PointID = b.PointID
LEFT OUTER JOIN TEMP c ON a.Record_no = c.Record_no - 2 and a.SId = c.SId and a.PointID = c.PointID) E
WHERE
E.StatusID = 2
AND [UTCSysTime] >= @StartTime
AND [UTCSysTime] <= @EndTime
) [Table_T]
WHERE
[UTCSysTime] > @StartTime
AND [UTCSysTime] <= @EndTime
我试图在SSMS上运行查询,并且两者都工作良好。我尝试使用SQL事件探查器,但是我的帐户没有权限。因此,我将日志放入源代码中。而且我看到一些记录需要50-60分钟才能读取和写入文件。
日志为:
2019-09-09 07:48:40.5242 |调试|结束写入行号226 |例外:
2019-09-09 07:48:40.5522 |调试|开始写行号227 |例外:
2019-09-09 07:48:40.5802 |调试|结束写行号227 |例外:
2019-09-09 07:48:40.6072 |调试|开始写行号228 |例外:
2019-09-09 07:48:40.6352 |调试|结束写行号228 |例外:
2019-09-09 07:48:40.6632 |调试|开始写行号229 |例外:
2019-09-09 08:20:50.3977 |调试|结束写行号229 |例外:
2019-09-09 08:20:50.4337 |调试|开始写行号230 |例外:
2019-09-09 08:20:50.4667 |调试|结束写行号230 |例外:
2019-09-09 08:20:50.5047 |调试|开始写行号231 |例外:
2019-09-09 08:20:50.5387 |调试|结束写行号231 |例外:
答案 0 :(得分:0)
这里要做的第一件事是确定问题是输入还是输出。为此,我只需要注释掉所有输出代码,就可以了(只显示未注释的代码):
while (reader.Read())
{
count++;
}
Console.WriteLine(count);
如果仍然很慢,则问题出在数据库上。我们看不到您的查询,表,索引或数据-因此我们无法帮助您对其进行调整,但是:那是您需要查找的地方。
如果没有输出代码的情况下速度很快,则问题出在您的编写代码中。您显示ExtendedStream.CreateMemoryStream
;这似乎不是常规框架的一部分,所以我无法评论它的预期执行方式,但是坦白地说,如果您正在编写文件,我会尝试使用内置框架类型尝试为此-FileStream
等
我还将最小化Console
输出的数量,也许只显示每N行更新N个。您不是要配置控制台。