【发布时间】:2015-09-10 18:19:11
【问题描述】:
我有以下用 C# 编写的代码,但据此,将数据从 Oracle 数据库迁移到 Elasticsearch 需要 4-5 天。我分批插入 100 条记录。有没有其他方法可以更快地迁移 400 万条记录(如果可能的话,可能在不到一天的时间内)?
public static void Selection()
{
for(int i = 1; i < 4000000; i += 1000)
{
for(int j = i; j < (i+1000); j += 100)
{
OracleCommand cmd = new OracleCommand(BuildQuery(j),
oracle_connection);
OracleDataReader reader = cmd.ExecuteReader();
List<Record> list=CreateRecordList(reader);
insert(list);
}
}
}
private static List<Record> CreateRecordList(OracleDataReader reader)
{
List<Record> l = new List<Record>();
string[] str = new string[7];
try
{
while (reader.Read())
{
for (int i = 0; i < 7; i++)
{
str[i] = reader[i].ToString();
}
Record r = new Record(str[0], str[1], str[2], str[3],
str[4], str[5], str[6]);
l.Add(r);
}
}
catch (Exception er)
{
string msg = er.Message;
}
return l;
}
private static string BuildQuery(int from)
{
int to = from + change - 1;
StringBuilder builder = new StringBuilder();
builder.AppendLine(@"select * from");
builder.AppendLine("(");
builder.AppendLine("select FIELD_1, FIELD_2,
FIELD_3, FIELD_4, FIELD_5, FIELD_6,
FIELD_7, ");
builder.Append(" row_number() over(order by FIELD_1)
rn");
builder.AppendLine(" from tablename");
builder.AppendLine(")");
builder.AppendLine(string.Format("where rn between {0} and {1}",
from, to));
builder.AppendLine("order by rn");
return builder.ToString();
}
public static void insert(List<Record> l)
{
try
{
foreach(Record r in l)
client.Index<Record>(r, "index", "type");
}
catch (Exception er)
{
string msg = er.Message;
}
}
【问题讨论】:
-
将
client.Index替换为client.IndexMany(..)并尝试找出批量插入的最佳块大小elastic.co/guide/en/elasticsearch/guide/current/… -
我需要 4-5 天 .. 你跑过看看是否真的需要 4/5 天才能迁移 4M 行?
-
ROW_NUMBER()函数会对性能产生负面影响,而且您正在运行它数千次。你已经在使用OracleDataReader——它不会一次将所有四百万行拉到你的机器上,它基本上是一次流式传输一个或几个。相反,您应该有一个查询,并且在构建Record对象时,每隔 100 或 500 或 1000 个(例如,保留一个递增每个循环的count),提交它们(例如在count % 500 == 0)。这必须在几分钟或几小时内完成,而不是几天。 -
您确定要插入任何行吗?我不认为语法执行和插入。
标签: c# .net oracle elasticsearch nest