我有一个包含超过300,000条记录的数据表,这相当于超过2.000.000个单词。我有一个算法可以从每个记录中获取所有单词并且运行良好,但我觉得它看起来有点慢。
我想加快这个计划。
程序就是这样的;
我搜索了一些关于加快这个程序的标题。
但我担心检查每个单词包含或使单词字段成为主要字符(我不知道它是否有效)或者在没有检查的情况下获取所有单词,并且在使用了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);
}
}
}
答案 0 :(得分:4)
可能最有效的方法是在数据库中进行过滤,而不是先将所有内容加载到内存中。但是,您也可以通过不将所有内容加载到DataTable
来改善效果,但如果您使用SqlDataReader
和HashSet<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通过列表查找给定单词,如果找不到则将新单词插入排序列表中,如果找到则跳过它。
这是一款更适合您软件的解决方案。