C#DataTable过滤器最快的方式

时间:2016-08-23 07:49:51

标签: c# algorithm performance linq datatable

我有一个包含超过300,000条记录的数据表,这相当于超过2.000.000个单词。我有一个算法可以从每个记录中获取所有单词并且运行良好,但我觉得它看起来有点慢。

我想加快这个计划。

程序就是这样的;

  1. 将所有记录从数据库获取到数据表。
  2. 循环数据并从每条记录中获取所有单词。
  3. 对于每个单词,检查新数据表是否包含该单词,如果没有添加到新数据表。
  4. 我搜索了一些关于加快这个程序的标题。

    1. 使用foreach还是? (我认为,没有区别)
    2. 用于检查数据表是否有单词,使用DataTable.Select()或Linq(实际上Linq更快)
    3. 但我担心检查每个单词包含或使单词字段成为主要字符(我不知道它是否有效)或者在没有检查的情况下获取所有单词,并且在使用了distinc之后完成所有单词。

      你能给我一些建议吗?感谢。

              DataTable dtProducts = getProducts();
              bool contains;
              string[] keys;
      
              dt.Columns.Add("keyword", typeof(string));
      
              for (int i = 0; i < dtProducts.Rows.Count; i++) //114040
              {
                  keys = GetWords(dtProducts.Rows[i]["name"].ToString().Trim());
      
                  foreach (string key in keys)
                  {
                      DataRow dr = dt.NewRow();
                      dr["keyword"] = key;
      
                      contains = dt.AsEnumerable().Any(row => key == row.Field<string>("keyword"));
      
                      if (!contains)
                      {
                          dt.Rows.Add(dr);
                      }
                  }
              }
      

3 个答案:

答案 0 :(得分:4)

可能最有效的方法是在数据库中进行过滤,而不是先将所有内容加载到内存中。但是,您也可以通过不将所有内容加载到DataTable来改善效果,但如果您使用SqlDataReaderHashSet<string>代替:

private static readonly char[] WordSeparator = { ' ', '\t', ',', '.', ':' }; // to be continued
// ....


HashSet<string> allUniqueWords = new HashSet<string>();
using (var con = new SqlConnection(Properties.Settings.Default.ConnectionString))
using (var cmd = new SqlCommand("SELECT DISTINCT ColumnName FROM dbo.TableName", con))
{
    con.Open();
    using (var rd = cmd.ExecuteReader())
    {
        string[] words = rd.GetString(0).Split(WordSeparator, StringSplitOptions.RemoveEmptyEntries);
        foreach (string word in words)
            allUniqueWords.Add(word);
    }
}

答案 1 :(得分:1)

Here你可以看到最快的方法是和Linq一起使用Parallel:

        var sampleResults = from DataRow sampleRow in dataTableLocal.AsEnumerable()
                            where sampleRow.Field<string>("FirstColumn") == symbolName
                            select sampleRow;

        Parallel.ForEach(sampleResults, sampleRow =>
        {
            string sval = sampleRow["SecondColumn"].ToString();
        });

答案 2 :(得分:0)

由于新添加的单词并且未对其进行排序,您的软件将呈指数级变慢,因此对于记录中的每个单词,它将全部通过它们。

要做的一件事是将数据表设为列表并将单词插入列表。在开始时,它将为空,因此您可以添加第一个单词。然后,您可以Binary Search通过列表查找给定单词,如果找不到则将新单词插入排序列表中,如果找到则跳过它。

这是一款更适合您软件的解决方案。