从数据库减少 CPU 远程 select 上的负载
Reducing CPU Load on a remote select from a database
我正在远程 select 从自定义生产数据库中获取结果,标准是从 C# 应用程序大约三分钟。
每次执行 select 命令时,我使用的服务器 PC CPU 都会上升到 50% 左右。但可以肯定的是,负载应该在我连接的数据库上吗?
为什么 C# 应用程序会飙升至 50%,直到检索数据进行读取?
一些背景
- 我通过调试发现 Select 语句在
远程数据库大约需要 30-40 秒,记住我 select 使用索引列的条件。
- 在从远程数据库 selecting 数据的同时,我监视了 TaskManager 并且 CPU 处于 50% 直到 select 完成..这个每个循环可以持续大约 30-40 秒。
- 如果我select在远程数据库的本地sql引擎中,select上没有延迟,数据(如果有的话)是return立即编辑。
- 我知道占用 CPU 负载的不是结果集的解析,因为一些 select 将 return 什么都没有。
这是我正在使用的一些代码。
OdbcConnection remoteConn = new OdbcConnection(ConfigurationManager.ConnectionStrings["remoteConnectionString"].ToString());
remoteConn.Open();
OdbcCommand remoteCommand = new OdbcCommand();
remoteCommand.Connection = remoteConn;
using (remoteConn)
{
string localSql = "";
string remoteSql = "select * from tracking where last_update > 212316247440000000"; // Julian No = 2015-07-12 11:24:00
remoteCommand.CommandText = remoteSql;
OdbcDataReader remoteReader;
remoteReader = remoteCommand.ExecuteReader();
while (remoteReader.Read())
{
for (int i = 0; i < 68; i++)
{
localSql += ",'" + remoteReader[i].ToString() + "'";
}
}
}
我 运行 对应用程序进行了性能和诊断测试,得到了这个结果。
如果有的话,我怎样才能减少这种 CPU 负荷甚至完全根除它。这完全不同寻常,我不知道该怎么做。
谢谢
难道是解析结果?您是否正在使用某种自动将结果集解析为域对象的数据层?那可能会非常 CPU 激烈..
感谢您提供信息,丹。这是我的想法...
我认为您的应用消耗如此多的主要原因 CPU 是因为您使用的驱动程序。
由于您要连接到 SQL 服务器数据库,因此您应该使用 SQL 服务器驱动程序,它知道如何优化客户端和服务器之间的数据传输。
要使用适当的驱动程序,请确保使用 SqlConnection
、SqlCommand
等
这将允许 SQL 服务器在您查询数据 reader.
时将结果 流式传输 到您的客户端
其次,不要在DbCommand
对象上使用ExecuteReader()
方法。 SQL 服务器驱动程序独有的众多精彩功能之一是 ExecuteReaderAsync()
方法。
由于此命令是 IO 绑定操作(不是计算绑定),因此无需阻塞调用线程。当结果返回时,它们将到达 IO 完成线程。
这里是您的代码在更改后的样子的代码示例。
using (var remoteConn = new SqlConnection(ConfigurationManager.ConnectionStrings["remoteConnectionString"].ToString()))
{
remoteConn.Open();
using (var remoteCommand = new SqlCommand())
{
remoteCommand.Connection = remoteConn;
string localSql = "";
string remoteSql = "select * from tracking where last_update > 212316247440000000"; // Julian No = 2015-07-12 11:24:00
remoteCommand.CommandText = remoteSql;
var remoteReader = await remoteCommand.ExecuteReaderAsync();
while (remoteReader.Read())
{
for (int i = 0; i < 68; i++)
{
localSql += ",'" + remoteReader[i].ToString() + "'";
}
}
}
}
我假设 select 命令是 运行 来自另一台计算机而不是托管 SQL 数据库的计算机。
说实话有点莫名其妙。我唯一想到的是传递和处理元数据可能需要时间。您是否尝试过将查询更改为 return 只说一条数据?
例如:
select top 1 last_update from tracking where last_update > 212316247440000000
select count (*) from tracking where last_update > 212316247440000000
这将阐明问题是否是由数据+元数据引起的。
您的 IO Bound
操作的最佳方式是使用 Task
,因为它不需要更改现有代码:
var task = Task.Factory.StartNew(() => {
//your code or @Randy code with little change here:
using (var remoteConn = new SqlConnection(ConfigurationManager.ConnectionStrings["remoteConnectionString"].ToString()))
{
remoteConn.Open();
using (var remoteCommand = new SqlCommand())
{
remoteCommand.Connection = remoteConn;
string localSql = "";
string remoteSql = "select * from tracking where last_update > 212316247440000000"; // Julian No = 2015-07-12 11:24:00
remoteCommand.CommandText = remoteSql;
var remoteReader = remoteCommand.ExecuteReader();
while (remoteReader.Read())
{
for (int i = 0; i < 68; i++)
{
localSql += ",'" + remoteReader[i].ToString() + "'";
}
}
}
}
});
//use can use 'task.wait();' to waiting for complete the task.
我正在远程 select 从自定义生产数据库中获取结果,标准是从 C# 应用程序大约三分钟。
每次执行 select 命令时,我使用的服务器 PC CPU 都会上升到 50% 左右。但可以肯定的是,负载应该在我连接的数据库上吗?
为什么 C# 应用程序会飙升至 50%,直到检索数据进行读取?
一些背景
- 我通过调试发现 Select 语句在 远程数据库大约需要 30-40 秒,记住我 select 使用索引列的条件。
- 在从远程数据库 selecting 数据的同时,我监视了 TaskManager 并且 CPU 处于 50% 直到 select 完成..这个每个循环可以持续大约 30-40 秒。
- 如果我select在远程数据库的本地sql引擎中,select上没有延迟,数据(如果有的话)是return立即编辑。
- 我知道占用 CPU 负载的不是结果集的解析,因为一些 select 将 return 什么都没有。
这是我正在使用的一些代码。
OdbcConnection remoteConn = new OdbcConnection(ConfigurationManager.ConnectionStrings["remoteConnectionString"].ToString());
remoteConn.Open();
OdbcCommand remoteCommand = new OdbcCommand();
remoteCommand.Connection = remoteConn;
using (remoteConn)
{
string localSql = "";
string remoteSql = "select * from tracking where last_update > 212316247440000000"; // Julian No = 2015-07-12 11:24:00
remoteCommand.CommandText = remoteSql;
OdbcDataReader remoteReader;
remoteReader = remoteCommand.ExecuteReader();
while (remoteReader.Read())
{
for (int i = 0; i < 68; i++)
{
localSql += ",'" + remoteReader[i].ToString() + "'";
}
}
}
我 运行 对应用程序进行了性能和诊断测试,得到了这个结果。
如果有的话,我怎样才能减少这种 CPU 负荷甚至完全根除它。这完全不同寻常,我不知道该怎么做。
谢谢
难道是解析结果?您是否正在使用某种自动将结果集解析为域对象的数据层?那可能会非常 CPU 激烈..
感谢您提供信息,丹。这是我的想法...
我认为您的应用消耗如此多的主要原因 CPU 是因为您使用的驱动程序。
由于您要连接到 SQL 服务器数据库,因此您应该使用 SQL 服务器驱动程序,它知道如何优化客户端和服务器之间的数据传输。
要使用适当的驱动程序,请确保使用 SqlConnection
、SqlCommand
等
这将允许 SQL 服务器在您查询数据 reader.
时将结果 流式传输 到您的客户端其次,不要在DbCommand
对象上使用ExecuteReader()
方法。 SQL 服务器驱动程序独有的众多精彩功能之一是 ExecuteReaderAsync()
方法。
由于此命令是 IO 绑定操作(不是计算绑定),因此无需阻塞调用线程。当结果返回时,它们将到达 IO 完成线程。
这里是您的代码在更改后的样子的代码示例。
using (var remoteConn = new SqlConnection(ConfigurationManager.ConnectionStrings["remoteConnectionString"].ToString()))
{
remoteConn.Open();
using (var remoteCommand = new SqlCommand())
{
remoteCommand.Connection = remoteConn;
string localSql = "";
string remoteSql = "select * from tracking where last_update > 212316247440000000"; // Julian No = 2015-07-12 11:24:00
remoteCommand.CommandText = remoteSql;
var remoteReader = await remoteCommand.ExecuteReaderAsync();
while (remoteReader.Read())
{
for (int i = 0; i < 68; i++)
{
localSql += ",'" + remoteReader[i].ToString() + "'";
}
}
}
}
我假设 select 命令是 运行 来自另一台计算机而不是托管 SQL 数据库的计算机。
说实话有点莫名其妙。我唯一想到的是传递和处理元数据可能需要时间。您是否尝试过将查询更改为 return 只说一条数据?
例如:
select top 1 last_update from tracking where last_update > 212316247440000000
select count (*) from tracking where last_update > 212316247440000000
这将阐明问题是否是由数据+元数据引起的。
您的 IO Bound
操作的最佳方式是使用 Task
,因为它不需要更改现有代码:
var task = Task.Factory.StartNew(() => {
//your code or @Randy code with little change here:
using (var remoteConn = new SqlConnection(ConfigurationManager.ConnectionStrings["remoteConnectionString"].ToString()))
{
remoteConn.Open();
using (var remoteCommand = new SqlCommand())
{
remoteCommand.Connection = remoteConn;
string localSql = "";
string remoteSql = "select * from tracking where last_update > 212316247440000000"; // Julian No = 2015-07-12 11:24:00
remoteCommand.CommandText = remoteSql;
var remoteReader = remoteCommand.ExecuteReader();
while (remoteReader.Read())
{
for (int i = 0; i < 68; i++)
{
localSql += ",'" + remoteReader[i].ToString() + "'";
}
}
}
}
});
//use can use 'task.wait();' to waiting for complete the task.