C# 有没有直接的方法可以将数据加载到内存中,而不必加载到数据库服务器上?
我正在尝试从sql server和oracle rdbms读取数百万数据C# 有没有直接的方法可以将数据加载到内存中,而不必加载到数据库服务器上?,c#,ado.net,bigdata,datareader,dataadapter,C#,Ado.net,Bigdata,Datareader,Dataadapter,我正在尝试从sql server和oracle rdbms读取数百万数据 Sql Server - select Id as LinkedColumn,CompareColumn from Source order by LinkedColumn Oracle -select Id as LinkedColumn,CompareColumn from Target order by LinkedColumn 此数据库位于不同的服务器上,我想从不同的服务器读取此数据 所以,我们的想法是尽可能让数
Sql Server - select Id as LinkedColumn,CompareColumn from Source order by LinkedColumn
Oracle -select Id as LinkedColumn,CompareColumn from Target order by LinkedColumn
此数据库位于不同的服务器上,我想从不同的服务器读取此数据
所以,我们的想法是尽可能让数据库服务器保持空闲
我正在考虑将这数百万数据分块读取,而不是使用data reader读取数据,data reader将在数据库上执行整个查询,数据库服务器将在内存流中打开这些记录,data reader将从中读取这些记录
由于数据库服务器上的负载,当存在多个作业时,这将花费大量时间
Records in Source : 12377200
Records in Target : 12266800
因为这个订单,它花费了太多的时间
那个么,有并没有任何方法可以在数据库上执行查询,并以某种方式将数据直接放入我的服务器内存(datatable或list或array
等),而无需在数据库服务器上加载
我下面的代码占用了2400万条记录太多的时间(仅从源和目标读取数据就超过2小时)
代码:
public void Test(SqlConnection srcCon, SqlConnection tgtCon)
{
int srcChunkSize = 1000;
int srcCurCount = 1;
int tgtChunkSize = 1000;
int tgtCurCount = 1;
bool srcBreak = false;
bool tgtBreak = false;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var da1 = new SqlDataAdapter(null, srcCon);
var da2 = new SqlDataAdapter(null, tgtCon);
da1.SelectCommand.CommandTimeout = 0;
da2.SelectCommand.CommandTimeout = 0;
while (true)
{
var srcDt = new DataTable();
var tgtDt = new DataTable();
if (!srcBreak)
{
string srcQuery = "select Id as LinkedColumn,CompareColumn from Source order by LinkedColumn" +
" OFFSET ((" + srcCurCount + " - 1) * " + srcChunkSize + " ) ROWS FETCH NEXT " + srcChunkSize + " ROWS ONLY;";
da1.SelectCommand.CommandText = srcQuery;
srcDt = GetDatatable(da1);
}
if (!tgtBreak)
{
string tgtQuery = "select Id as LinkedColumn,CompareColumn from Target order by LinkedColumn" +
" OFFSET ((" + tgtCurCount + " - 1) * " + tgtChunkSize + " ) ROWS FETCH NEXT " + tgtChunkSize + " ROWS ONLY;";
da2.SelectCommand.CommandText = tgtQuery;
tgtDt = GetDatatable(da2);
}
if (srcDt.Rows.Count == 0) srcBreak = true;
srcCurCount++;
if (tgtDt.Rows.Count == 0) tgtBreak = true;
tgtCurCount++;
if (srcBreak && tgtBreak) break;
}
stopwatch.Stop();
string a = stopwatch.Elapsed.ToString(@"d\.hh\:mm\:ss");
Console.WriteLine(a);
}
private DataTable GetDatatable(SqlDataAdapter da)
{
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
在不知道自己的最终目标是什么的情况下,很难给出一个好的答案。例如,最好的答案可能是在存储过程中而不是在c#中执行任务 然而,为了简单地加快进程,您可以使用并行编程。这里有一个很好的起点: 也请考虑后退一步,看看你的体系结构。您可能会从旋转图形数据库和从Oracle执行批导出\导入中获益。图形数据库在复杂的海量关系查询中效率更高。SqlDataReader: 保持连接打开直到我们完成(不要忘记关闭它!)。 通常只能迭代一次 对于更新回数据库没有那么有用 另一方面,它: 一次内存中只有一条记录,而不是整个结果集(这可能是巨大的) 大约是我们在那一次迭代中所能达到的最快速度 允许我们更快地开始处理结果(一旦第一条记录可用) SqlDataAdapter/DataSet 让我们在加载数据后立即关闭连接,甚至可以为我们自动关闭连接 所有结果都在内存中可用 我们可以根据需要对它进行多次迭代,甚至可以通过索引查找特定记录 有一些内置的功能,可以更新回数据库 代价是: 更高的内存使用率 在使用任何数据之前,我们都会等待所有数据加载完毕 您可以在以下网址查看原始帖子:
谢谢。那么你是说我应该使用导出数据到图形数据库,然后使用图形数据库中的数据做任何我想做的事情吗?是的。看看Neo4j,我不知道如何一下子把整个东西读入内存(你现在正在做什么)与使用datareader逐个读取相比,将在数据库上施加更少的负载。@数据读取器的Evk问题是,当我在数据库流中执行executereader时,结果集将被维护并逐1读取,所以在我读取完整个结果集之前,负载一直在数据库服务器上。如果我错了,请纠正我。您的1000条记录的块太多了小的确保这些表上的索引涵盖了选定的列-索引应位于
Id
列上,并包括CompareColumn
@ZoharPeled虽然我在Id列上有索引,但花费的时间太多了。那么,您建议块大小是多少?对于1230万条记录,我建议至少有100000条记录作为缓冲区。选择1000条记录意味着您必须运行select语句12300次。。。