我是多线程新手和SQL新手,所以请原谅任何新手的错误。
我试图异步执行许多SQL查询。查询是同一数据库中同一个表中的所有select语句。我可以同步运行它们并且一切正常,但是测试一小部分会让我相信同步运行所有查询大约需要150个小时,这太长了。因此,我试图弄清楚如何并行运行它们。
我试图在run a method multiple times simultaneously in c#的答案之后对代码进行建模,但我的代码没有正确执行(这是错误的,虽然我不知道具体如何。代码只是说错误发生了。)
这就是我所拥有的(我实际做的更小更简单的版本):
class Program
{
static void Main(string[] args)
{
List<string> EmployeeIDs = File.ReadAllLines(/* Filepath */);
List<Tuple<string, string>> NamesByID = new List<Tuple<string, string>>();
//What I do not want to do (because it takes too long) ...
using (SqlConnection conn = new SqlConnection(/* connection string */))
{
foreach (string id in EmployeeIDs)
{
using (SqlCommand cmd = new SqlCommand("SELECT FirstName FROM Employees WITH (NOLOCK) WHERE EmployeeID = " + id, conn))
{
try
{
conn.Open();
NamesByID.Add(new Tuple<string, string> (id, cmd.ExecuteScalar().ToString()));
}
finally
{
conn.Close();
}
}
}
}
//What I do want to do (but it errors) ...
var tasks = EmployeeIDs.Select(id => Task<Tuple<string, string>>.Factory.StartNew(() => RunQuery(id))).ToArray();
Task.WaitAll(tasks);
NamesByID = tasks.Select(task => task.Result).ToList();
}
private static Tuple<string, string> RunQuery(string id)
{
using (SqlConnection conn = new SqlConnection(/* connection string */))
{
using (SqlCommand cmd = new SqlCommand("SELECT FirstName FROM Employees WITH (NOLOCK) WHERE EmployeeID = " + id, conn))
{
try
{
conn.Open();
return new Tuple<string, string> (id, cmd.ExecuteScalar().ToString());
}
finally
{
conn.Close();
}
}
}
}
}
注意:我并不关心这是多线程的(task,parallel.foreach,backgroundworker等)。这将用于运行约30,000个精选查询一次,所以我只需要它快速运行(我希望~8小时=一个工作日,但我会采取我能得到的)一次。它不一定非常漂亮。
提前谢谢!
答案 0 :(得分:3)
这是完全错误的。您应该构建一个查询以选择所需的所有FirstNames。如果你需要将一堆id传递给服务器,这没问题,只需使用table valued parameter(又名TVP),昏迷分隔的值列表实际上不能很好地扩展。如果正确写入查询并将表编入索引,则应该非常快。 100k行表是一张小表。
然后查询可能如下所示
SELECT DollarAmount, comp.CompanyID
FROM Transactions
JOIN (SELECT MIN(TransactionID) as minTransactionID, CompanyID
FROM CompanyTransactions
GROUP BY CompanyID
) AS comp
ON Transactions.TransactionID = comp.minTransactionID
JOIN @IDList ON id = comp.CompanyID
如果TVP中的ID不是唯一的,则可以使用IN
代替JOIN
。
顺便说一下。你知道NOLOCK的意思吗?如果您是数据库的唯一用户并使用单线程或不修改任何数据,那么您是安全的。除此之外,这意味着您可以轻松获得:
答案 1 :(得分:1)
您想要执行一个查询以获取所有ID /名称组合,然后将它们放入字典中(以便快速访问)。这将消除运行30,000个查询的非常缓慢的过程,并降低代码的复杂性。
如果您发布了实际的SQL查询(如果需要可以更改列和表名),我可以为您提供更具体的内容,但这应该是关闭的:
;WITH CompTransCTE AS (
SELECT CompanyID, MIN(TransactionID) AS TransactionID
FROM CompanyTransactions
WHERE CompanyID IN (/*Comma seperated list of values*/)
GROUP BY CompanyID
)
SELECT CT.CompanyID, T.DollarAmount, T.TransactionID
FROM Transactions AS T
INNER JOIN CompTransCTE AS CT ON CT.TransactionID = T.TransactionID;
答案 2 :(得分:0)
如果不在数据库中创建用户定义的表类型,您可以使用SqlBulkCopy将ID加载到临时表中,并在查询中引用它。
std::__cxx11::basic_string