当前位置: 首页 > 面试题库 >

如何使用C#将Oracle中的400万条记录更快地插入Elasticsearch表中?

金令秋
2023-03-14
问题内容

我有以下用C#编写的代码,但是据此,我需要4-5天的时间才能将数据从Oracle数据库迁移到Elasticsearch。我将以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;
            }
        }

问题答案:

ROW_NUMBER()功能将对性能产生负面影响,并且您正在运行数千次。您已经在使用OracleDataReader-它不会一次将所有四百万行都拉到您的计算机上,它基本上是一次流一次或几行。

这必须在几分钟或几小时内完成,而不是几天-我们有几个进程以类似的方式在Sybase和SQL Server之间移动数百万条记录,并且花费不到五分钟。

也许试一下:

OracleCommand cmd = new OracleCommand("SELECT ... FROM TableName", oracle_connection);
int batchSize = 500;    
using (OracleDataReader reader = cmd.ExecuteReader())
{
    List<Record> l = new List<Record>(batchSize);
    string[] str = new string[7];
    int currentRow = 0;

    while (reader.Read())
    {
        for (int i = 0; i < 7; i++)
        {
            str[i] = reader[i].ToString();
        }

        l.Add(new Record(str[0], str[1], str[2], str[3], str[4], str[5], str[6]));

        // Commit every time batchSize records have been read
        if (++currentRow == batchSize)
        {
            Commit(l);
            l.Clear();
            currentRow = 0;
        }
    }

    // commit remaining records
    Commit(l);
}

以下是Commit可能的样子:

public void Commit(IEnumerable<Record> records)
{
    // TODO: Use ES's BULK features, I don't know the exact syntax

    client.IndexMany<Record>(records, "index", "type");
    // client.Bulk(b => b.IndexMany(records))... something like this
}


 类似资料:
  • 我有一个查询,它从另一个表中填充表数据。现在它看起来像这样。 在10 000条记录上,它执行大约10秒。但是会有10,000,000条记录的情况,恐怕它会很慢。我能做得更快吗?

  • 有一列我想检索并插入到另一个表中例如,下面是我想检索值的第一个表 我使用MSSQL2008

  • 问题内容: 我在MySQL中用一个表创建了一个数据库: 我尝试使用Java插入记录: 输出似乎成功返回: 但是,当我从MySQL中选择时,插入的记录为空: 为什么插入空白记录? 问题答案: 不,这是行不通的(不适用于真实数据): 更改为: 使用该sql创建一个PreparedStatment,并使用索引插入值:

  • 我想更新postgres表的一列。记录大约有5500万条,所以我们需要在10000条记录中更新它。注意:我们要更新所有行。但我们不想锁桌子。 我正在尝试以下查询- 我们如何为每10000条记录更新做一个循环? 如有任何建议和帮助,将不胜感激。 PostgreSQL 10.5

  • 我正在尝试从一个oracle数据库迁移到另一个。我的选择查询非常复杂,它返回大约2000万条记录。当我尝试执行时: 大约需要20个小时。 有什么不同的迁移方式吗?你能给我一些建议吗? 谢谢你的建议。 编辑:我创建了一个新表格,如下所示 将表XYZ创建为从yyy join zzz join ttt等中选择a,b,c,bla blaa 大约需要2分钟。 现在我正在尝试从XYZ插入到我的原始表。 还剩1

  • 在我的用户表中,我需要在凌晨12点将“每日”列恢复为默认值“1”。 是否有一种方法可以让我在每天上午12点将值恢复为默认值1或将100万条记录的值更新为1,而不延迟任何时间(意味着所有用户的“每日”列将同时更新)? 注:“每日”列用于确定用户是否已“用完”其每日单击。用户每天有1次机会点击按钮(有点像奖励框)。单击按钮后,每日将更新为“0”,直到第二天才能再次单击按钮。