ILo*_*low 6 c# ado.net datareader bigdata
我正在尝试加载来自不同RDBMS的2个巨大的结果集(源和目标),但我正在努力的问题是在内存中获得这2个巨大的结果集.
下面考虑从源和目标中提取数据的查询:
Total jobs running in parallel = 3
Time taken by Job1 = 01:47:25
Time taken by Job1 = 01:47:25
Time taken by Job1 = 01:48:32
There is no index on Id Column.
Run Code Online (Sandbox Code Playgroud)
来源: 12377200
目标记录: 12266800
以下是我尝试过的一些统计方法:
1)2个开放数据读取器方法,用于读取源和目标数据:
Total jobs = 1
Chunk size : 100000
Time Taken : 02:02:48
There is no index on Id Column.
Run Code Online (Sandbox Code Playgroud)
select Id as LinkedColumn,CompareColumn from Source order by LinkedColumn 这很糟糕.
2)通过块读取方法来读取源和目标数据的块:
Total jobs = 1
Chunk size : 100000
Time Taken : 00:39:40
Index is present on Id column.
Run Code Online (Sandbox Code Playgroud)
3)通过块读取方法读取源和目标数据的块:
Total jobs = 1
Index : Yes
Time: 00:01:43
Run Code Online (Sandbox Code Playgroud)
4)2个开放式数据读取器方法,用于读取源和目标数据:
Total jobs running in parallel = 3
Index : Yes
Time: 00:25:12
Run Code Online (Sandbox Code Playgroud)
5)2个开放数据读取器方法,用于读取源和目标数据:
Source Sql Query Execution time in sql server management studio: 00:01:41
Target Sql Query Execution time in sql server management studio:00:01:40
Run Code Online (Sandbox Code Playgroud)
我确实观察到虽然在LinkedColumn上有索引确实提高了性能,但问题是我们正在处理可能具有索引或可能没有索引的第三方RDBMS表.
我们希望保持数据库服务器尽可能免费,因此数据读取器方法似乎并不是一个好主意,因为会有大量并行运行的作业,这将给我们不想要的数据库服务器带来如此大的压力.
因此,我们希望从源到目标获取资源内存中的记录,并进行1-1比较记录比较,保持数据库服务器空闲.
注意:我想在我的c#应用程序中执行此操作,并且不想使用select Id as LinkedColumn,CompareColumn from Target order by LinkedColumn或var dr = command.ExecuteReader();.
更新:
源Sql查询在sql server management studio中的执行时间:00:01:41
目标Sql查询sql server management studio中的执行时间:00:01:40
在内存中读取大量结果集的最佳方法是什么?
代码:
static void Main(string[] args)
{
// Running 3 jobs in parallel
//Task<string>[] taskArray = { Task<string>.Factory.StartNew(() => Compare()),
//Task<string>.Factory.StartNew(() => Compare()),
//Task<string>.Factory.StartNew(() => Compare())
//};
Compare();//Run single job
Console.ReadKey();
}
public static string Compare()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var srcConnection = new SqlConnection("Source Connection String");
srcConnection.Open();
var command1 = new SqlCommand("select Id as LinkedColumn,CompareColumn from Source order by LinkedColumn", srcConnection);
var tgtConnection = new SqlConnection("Target Connection String");
tgtConnection.Open();
var command2 = new SqlCommand("select Id as LinkedColumn,CompareColumn from Target order by LinkedColumn", tgtConnection);
var drA = GetReader(command1);
var drB = GetReader(command2);
stopwatch.Stop();
string a = stopwatch.Elapsed.ToString(@"d\.hh\:mm\:ss");
Console.WriteLine(a);
return a;
}
private static IDataReader GetReader(SqlCommand command)
{
command.CommandTimeout = 0;
return command.ExecuteReader();//Culprit
}
Run Code Online (Sandbox Code Playgroud)
(据我所知)没有什么比DataReader更快的用于获取数据库记录的。
使用大型数据库面临很多挑战,在不到2秒的时间内读取1000万条记录非常好。
如果您想更快一点,可以:
使用sqlcmd.exe和Process类运行查询并将结果放入csv文件中,然后将csv读入c#。sqlcmd.exe旨在存档大型数据库,并且运行速度比c#接口快100倍。使用linq方法也比SQL Client类更快
并行查询并获取合并结果:https ://shahanayyub.wordpress.com/2014/03/30/how-to-load-large-dataset-in-datagridview/
最简单的方法(对于SELECT *全部而言,IMO最好的方法)是向其扔硬件:https : //blog.codinghorror.com/hardware-is-cheap-programmers-are-expensive/
还要确保您正在发布模式下在PROD硬件上进行测试,因为这可能会使基准测试产生偏差。