我正在从DataTables中的三个制表符分隔文件导入数据,然后我需要遍历主表的每一行并找到两个子表中的所有行.对于我从子表中找到的每个DataRow []数组,我必须再次单独遍历每一行并根据不同的参数检查值,最后我需要创建一个最终记录,这将是主人和两个孩子的合并表列.现在我已经完成了它的工作,但问题在于它的性能.我正在使用DataTable.Select来查找子表中的所有子行,我认为这些行非常慢.请记住表中没有任何主键,因为重复行是可接受的.目前我在主表中有1200行,在子表中有8000行,这样做的总时间是8分钟.
不知道如何提高性能.提前致谢
代码低于***************
DataTable rawMasterdt = importMasterFile();
DataTable rawDespdt = importDescriptionFile();
dsHelper = new DataSetHelper();
DataTable distinctdt = new DataTable();
distinctdt = dsHelper.SelectDistinct("DistinctOffers", rawMasterdt, "C1");
if (distinctdt.Rows.Count > 0)
{
int count = 0;
foreach (DataRow offer in distinctdt.Rows)
{
string exp = "C1 = " + "'" + offer[0].ToString() + "'" + "";
DataRow masterRow = rawMasterdt.Select(exp)[0];
count++;
txtBlock1.Text = "Importing Offer " + count.ToString() + " of " + distinctdt.Rows.Count.ToString();
if (masterRow != null )
{
Product newProduct = new Product();
newProduct.Code = masterRow["C4"].ToString();
newProduct.Name = masterRow["C5"].ToString();
// -----
newProduct.Description = getProductDescription(offer[0].ToString(), rawDespdt);
newProduct.Weight = getProductWeight(offer[0].ToString(), rawDespdt);
newProduct.Price = getProductRetailPrice(offer[0].ToString(), rawDespdt);
newProduct.UnitPrice = getProductUnitPrice(offer[0].ToString(), rawDespdt);
// ------- more functions similar to above here
productList.Add(newProduct);
}
}
txtBlock1.Text = "Import Completed";
public string getProductDescription(string offercode, DataTable dsp)
{
string exp = "((C1 = " + "'" + offercode + "')" + " AND ( C6 = 'c' ))";
DataRow[] dRows = dsp.Select( exp);
string descrip = "";
if (dRows.Length > 0)
{
for (int i = 0; i < dRows.Length - 1; i++)
{
descrip = descrip + " " + dRows[i]["C12"];
}
}
return descrip;
}
Run Code Online (Sandbox Code Playgroud)
.Net 4.5和问题仍然存在.
以下是一个简单基准测试的结果,其中DataTable.Select和不同的字典实现比较CPU时间(结果以毫秒为单位)
#Rows Table.Select Hashtable[] SortedList[] Dictionary[]
1000 43,31 0,01 0,06 0,00
6000 291,73 0,07 0,13 0,01
11000 604,79 0,04 0,16 0,02
16000 914,04 0,05 0,19 0,02
21000 1279,67 0,05 0,19 0,02
26000 1501,90 0,05 0,17 0,02
31000 1738,31 0,07 0,20 0,03
Run Code Online (Sandbox Code Playgroud)
问题:
DataTable.Select方法在内部创建"System.Data.Select"类实例,此"Select"类根据查询中指定的字段(列)创建索引.Select类重新使用它创建的索引,但DataTable实现不会重用Select类实例,因此每次调用DataTable.Select时都会重新创建索引.(通过反编译System.Data可以观察到此行为)
解:
假设以下查询
DataRow[] rows = data.Select("COL1 = 'VAL1' AND (COL2 = 'VAL2' OR COL2 IS NULL)");
Run Code Online (Sandbox Code Playgroud)
而是使用与用作过滤器的列的值的不同值组合对应的键创建和填充字典.(这个相对昂贵的操作必须只进行一次,然后必须重新使用字典实例)
Dictionary<string, List<DataRow>> di = new Dictionary<string, List<DataRow>>();
foreach (DataRow dr in data.Rows)
{
string key = (dr["COL1"] == DBNull.Value ? "<NULL>" : dr["COL1"]) + "//" + (dr["COL2"] == DBNull.Value ? "<NULL>" : dr["COL2"]);
if (di.ContainsKey(key))
{
di[key].Add(dr);
}
else
{
di.Add(key, new List<DataRow>());
di[key].Add(dr);
}
}
Run Code Online (Sandbox Code Playgroud)
查询字典(可能需要多个查询)来过滤行并将结果合并到List中
string key1 = "VAL1//VAL2";
string key2 = "VAL1//<NULL>";
List<DataRow>() results = new List<DataRow>();
if (di.ContainsKey(key1))
{
results.AddRange(di[key1]);
}
if (di.ContainsKey(key2))
{
results.AddRange(di[key2]);
}
Run Code Online (Sandbox Code Playgroud)
可以使数据表与数据集中的其他数据表具有关系。请参阅http://msdn.microsoft.com/en-us/library/ay82azad%28VS.71%29.aspx进行一些讨论并作为浏览的起点。我没有太多使用它们的经验,但据我了解,它们会做你想做的事情(假设你的表格采用合适的格式)。我认为这些比手动过程具有更高的效率,但我可能是错的。可能值得看看它们是否适合您,并进行基准测试以查看它们是否有所改进......
| 归档时间: |
|
| 查看次数: |
14642 次 |
| 最近记录: |