2

我试图从xp_readerrorlogPowerShell 脚本中的扩展存储过程中读取第一行。

不幸的是,ExecuteReader()方法读取xp_readerrorlog存储过程返回的所有记录,有时是几百万行或几分钟。

我试图用谷歌搜索它,发现使用 DAO 可以读取 SQL Server 返回的数据,但 DAO 已被弃用,我不想走这条路。

BeginExecuteReader()似乎也无济于事,因为在执行完成之前没有迹象表明是否有任何数据已返回,等于ExecuteReader(). 使用大型记录集时,有没有其他方法可以只获得几行/页?

我知道我可以创建一个临时表,将数据转储到其中并SELECT TOP 1从中转储,但这会引入一些额外的 I/O,这不是我正在寻找的解决方案。

4

2 回答 2

0

我认为您对Execute 方法在 ServerConnection 上工作有一个小小的误解。它们对存储过程的运行方式没有影响。即使您使用ExecuteScalar(执行 Transact-SQL 语句并将第一行的第一列作为值类型返回。)然后整个存储过程将在服务器上运行,然后只返回第一个值。

您唯一可以提高性能的两个选项是创建一个返回所需行的新过程(Sql 性能改进和网络利用率改进)或使用临时表从存储过程返回单行(仅网络利用率改进) .

ServerConnection 上没有内置方法可以在 .Net 框架中执行您想要的操作。

于 2013-06-25T23:57:53.260 回答
0

从 .Net 4.5 开始,SqlCommand类有ExecuteReaderAsync()方法,SqlDataReader类有ReadAsync()方法。一旦 SQL Server 开始使用这些新方法将数据发送到客户端,就可以开始处理数据。

不幸的是,PowerShell 中没有 await 运算符,因此代码看起来不如 C# 中的漂亮。

$sqlInstance = 'SqlServerName';

$con = New-Object System.Data.SqlClient.SQLConnection;
$con.ConnectionString = "Data Source=$($sqlInstance);Integrated Security=SSPI;Asynchronous Processing=true;";
$con.Open();

$cmd = New-Object System.Data.SqlClient.SQLCommand;
$cmd.Connection = $con;

$cmd.CommandType = [System.Data.CommandType]::StoredProcedure;
$cmd.CommandText = 'xp_readerrorlog';

# add parameters
$cmd.Parameters.Add('p1', [System.Data.SqlDbType]::Int, 1) | out-null;
$cmd.Parameters['p1'].Value = 1;
$cmd.Parameters.Add('p2', [System.Data.SqlDbType]::Int, 1) | out-null;
$cmd.Parameters['p2'].Value = 1;

$cmd.Prepare();

$task = $cmd.ExecuteReaderAsync();

# wait for first rows
While ( $task.IsCompleted -ne $true ) {
    Start-Sleep -m 10;
}

# PowerShell does not have await operator so a SqlDataReader object can be retrieved this way
$reader = $task.GetAwaiter().GetResult();

# read first row
$reader.ReadAsync().GetAwaiter().GetResult() | out-null;

$reader['LogDate'];

$cmd.Cancel(); # cancel execution, there is no need to wait for the whole recordset to be transfered to the client

$con.Close();
于 2013-07-11T01:27:31.260 回答