C#:遍历一个巨大的数据表
使用for循环遍历包含大约40000条记录的数据表几乎需要4分钟。在循环中,我只是读取每行特定列的值,并将其浓缩为字符串 我没有打开任何数据库连接或其他东西,因为它是一个函数,接收一个数据表,遍历它并返回一个字符串 有没有更快的方法 代码如下:C#:遍历一个巨大的数据表,c#,loops,datatable,C#,Loops,Datatable,使用for循环遍历包含大约40000条记录的数据表几乎需要4分钟。在循环中,我只是读取每行特定列的值,并将其浓缩为字符串 我没有打开任何数据库连接或其他东西,因为它是一个函数,接收一个数据表,遍历它并返回一个字符串 有没有更快的方法 代码如下: private string getListOfFileNames(Datatable listWithFileNames) { string whereClause = ""; if (l
private string getListOfFileNames(Datatable listWithFileNames)
{
string whereClause = "";
if (listWithFileNames.Columns.Contains("Filename"))
{
whereClause = "where filename in (";
for (int j = 0; j < listWithFileNames.Rows.Count; j++)
whereClause += " '" + listWithFileNames.Rows[j]["Filename"].ToString() + "',";
}
whereClause = whereClause.Remove(whereClause.Length - 1, 1);
whereClause += ")";
return whereClause;
}
私有字符串getListOfFileNames(带有文件名的数据表列表)
{
字符串whereClause=“”;
if(listWithFileNames.Columns.Contains(“文件名”))
{
whereClause=“where filename in(”;
对于(int j=0;j
以下linq语句在变量的第一列上有where子句,在第三列上有concat子句
string CSVValues = String.Join(",", dtOutput.AsEnumerable()
.Where(a => a[0].ToString() == value)
.Select(b => b[2].ToString()));
第1步-通过分析器运行它,确保在优化时看到正确的东西 举个例子,我们确信有一个问题是数据库交互缓慢,当我们运行探查器时,数据库几乎没有出现 也就是说,可能的尝试:
- 如果内存可用,请将查询转换为列表,如下所示 将强制读取完整的数据库。否则linq可能会加载 执行多个db查询的块
- 将工作推送到数据库-如果可以创建查询,则向下修剪 您正在查看的数据,甚至为您计算字符串, 那可能更快
- 如果查询经常运行,但数据很少运行 更改,考虑将数据复制到本地数据库(如SQLite) 您正在使用远程数据库
- 如果您使用的是本地sql server,请尝试使用sqlite,它会更快 很多事情
var值=数据表
.可计算的()
.Select(row=>row.Field(“columnName”);
var colValueStr=string.join(“,”,value.ToArray());
尝试使用表达式在表中添加虚拟列。大概是这样的:
DataColumn dynColumn = new DataColumn();
{
dynColumn.ColumnName = "FullName";
dynColumn.DataType = System.Type.GetType("System.String");
dynColumn.Expression = "LastName+' '-ABC";
}
UserDataSet.Tables(0).Columns.Add(dynColumn);
在以后的代码中,您可以改用这个伪列。您不需要旋转任何循环来连接字符串。尝试使用并行for循环。。 下面是示例代码
Parallel.ForEach(dataTable.AsEnumerable(),
item => { str += ((item as DataRow)["ColumnName"]).ToString(); });
我把工作分成了小块,让每一块都由自己的线程处理。您可以通过改变线程数来微调线程数。尝试使用不同的数字,这样您就可以看到性能上的差异
private string getListOfFileNames(DataTable listWithFileNames)
{
string whereClause = String.Empty;
if (listWithFileNames.Columns.Contains("Filename"))
{
int nthreads = 8; // You can play with this parameter to fine tune and get your best time.
int load = listWithFileNames.Rows.Count / nthreads; // This will tell how many items reach thread mush process.
List<ManualResetEvent> mres = new List<ManualResetEvent>(); // This guys will help the method to know when the work is done.
List<StringBuilder> sbuilders = new List<StringBuilder>(); // This will be used to concatenate each bis string.
for (int i = 0; i < nthreads; i++)
{
sbuilders.Add(new StringBuilder()); // Create a new string builder
mres.Add(new ManualResetEvent(false)); // Create a not singaled ManualResetEvent.
if (i == 0) // We know were to put the very begining of your where clause
{
sbuilders[0].Append("where filename in (");
}
// Calculate the last item to be processed by the current thread
int end = i == (nthreads - 1) ? listWithFileNames.Rows.Count : i * load + load;
// Create a new thread to deal with a part of the big table.
Thread t = new Thread(new ParameterizedThreadStart((x) =>
{
// This is the inside of the thread, we must unbox the parameters
object[] vars = x as object[];
int lIndex = (int)vars[0];
int uIndex = (int)vars[1];
ManualResetEvent ev = vars[2] as ManualResetEvent;
StringBuilder sb = vars[3] as StringBuilder;
bool coma = false;
// Concatenate the rows in the string builder
for (int j = lIndex; j < uIndex; j++)
{
if (coma)
{
sb.Append(", ");
}
else
{
coma = true;
}
sb.Append("'").Append(listWithFileNames.Rows[j]["Filename"]).Append("'");
}
// Tell the parent Thread that your job is done.
ev.Set();
}));
// Start the thread with the calculated params
t.Start(new object[] { i * load, end, mres[i], sbuilders[i] });
}
// Wait for all child threads to finish their job
WaitHandle.WaitAll(mres.ToArray());
// Concatenate the big string.
for (int i = 1; i < nthreads; i++)
{
sbuilders[0].Append(", ").Append(sbuilders[i]);
}
sbuilders[0].Append(")"); // Close your where clause
// Return the finished where clause
return sbuilders[0].ToString();
}
// Returns empty
return whereClause;
}
私有字符串getListOfFileNames(带有文件名的数据表列表)
{
string whereClause=string.Empty;
if(listWithFileNames.Columns.Contains(“文件名”))
{
int nthreads=8;//您可以使用此参数进行微调并获得最佳时间。
int load=listWithFileNames.Rows.Count/nthreads;//这将告诉有多少项到达了线程mush进程。
List mres=new List();//这些人将帮助方法知道工作何时完成。
List sbuilders=new List();//这将用于连接每个bis字符串。
对于(int i=0;i
{
//这是线程的内部,我们必须取消绑定参数
对象[]变量=x作为对象[];
int-lIndex=(int)vars[0];
int uIndex=(int)vars[1];
ManualResetEvent ev=vars[2]作为ManualResetEvent;
StringBuilder sb=vars[3]作为StringBuilder;
布尔昏迷=假;
//连接字符串生成器中的行
对于(int j=lIndex;jprivate string getListOfFileNames(DataTable listWithFileNames)
{
string whereClause = String.Empty;
if (listWithFileNames.Columns.Contains("Filename"))
{
int nthreads = 8; // You can play with this parameter to fine tune and get your best time.
int load = listWithFileNames.Rows.Count / nthreads; // This will tell how many items reach thread mush process.
List<ManualResetEvent> mres = new List<ManualResetEvent>(); // This guys will help the method to know when the work is done.
List<StringBuilder> sbuilders = new List<StringBuilder>(); // This will be used to concatenate each bis string.
for (int i = 0; i < nthreads; i++)
{
sbuilders.Add(new StringBuilder()); // Create a new string builder
mres.Add(new ManualResetEvent(false)); // Create a not singaled ManualResetEvent.
if (i == 0) // We know were to put the very begining of your where clause
{
sbuilders[0].Append("where filename in (");
}
// Calculate the last item to be processed by the current thread
int end = i == (nthreads - 1) ? listWithFileNames.Rows.Count : i * load + load;
// Create a new thread to deal with a part of the big table.
Thread t = new Thread(new ParameterizedThreadStart((x) =>
{
// This is the inside of the thread, we must unbox the parameters
object[] vars = x as object[];
int lIndex = (int)vars[0];
int uIndex = (int)vars[1];
ManualResetEvent ev = vars[2] as ManualResetEvent;
StringBuilder sb = vars[3] as StringBuilder;
bool coma = false;
// Concatenate the rows in the string builder
for (int j = lIndex; j < uIndex; j++)
{
if (coma)
{
sb.Append(", ");
}
else
{
coma = true;
}
sb.Append("'").Append(listWithFileNames.Rows[j]["Filename"]).Append("'");
}
// Tell the parent Thread that your job is done.
ev.Set();
}));
// Start the thread with the calculated params
t.Start(new object[] { i * load, end, mres[i], sbuilders[i] });
}
// Wait for all child threads to finish their job
WaitHandle.WaitAll(mres.ToArray());
// Concatenate the big string.
for (int i = 1; i < nthreads; i++)
{
sbuilders[0].Append(", ").Append(sbuilders[i]);
}
sbuilders[0].Append(")"); // Close your where clause
// Return the finished where clause
return sbuilders[0].ToString();
}
// Returns empty
return whereClause;
}