C# 使用多线程执行SQL语句

C# 使用多线程执行SQL语句,c#,sql,.net,multithreading,oracle,C#,Sql,.net,Multithreading,Oracle,我有执行数据检索的代码——基本上执行3到12条SQL(oracle)read语句来检索有关对象的数据 不幸的是,它的运行速度很慢(特别是没有SQL语句,事实上我有这么多SQL语句——每条语句大约需要0.2秒,这意味着代码需要2秒才能完成) 我正在寻找提高绩效的方法。一种方法是将一些表合并到单个查询中(这可以将合并结果减少0.5秒)。然而,合并其余部分是没有意义的,因为在某些情况下,那里只有数据,而试图确定那里何时有数据需要封送可能会变得很棘手 我正在考虑在我的程序中引入线程,所以在初始查询之后,

我有执行数据检索的代码——基本上执行3到12条SQL(oracle)read语句来检索有关对象的数据

不幸的是,它的运行速度很慢(特别是没有SQL语句,事实上我有这么多SQL语句——每条语句大约需要0.2秒,这意味着代码需要2秒才能完成)

我正在寻找提高绩效的方法。一种方法是将一些表合并到单个查询中(这可以将合并结果减少0.5秒)。然而,合并其余部分是没有意义的,因为在某些情况下,那里只有数据,而试图确定那里何时有数据需要封送可能会变得很棘手

我正在考虑在我的程序中引入线程,所以在初始查询之后,我会为每个其他查询生成一个线程,以便它们同时执行。然而,我从来没有使用过线程,并且对引入死锁或其他陷阱保持警惕

当前,其他查询将结果封送到同一对象的不同部分。这是否会导致任何问题(即,由于我们通过对象中的不同部分/字段在不同线程中访问/更新同一对象?)。在所有线程完成后返回结果并封送到对象中是否更好


我知道这些类型的问题很难回答,因为它提供了更一般的建议,但如果有人认为这是一个好主意,或者有其他建议,我将不胜感激。

如果您只阅读(从中选择)-不要担心死锁。Oracle读数不可阻止(大部分)。将查询线程化到oracle的最大问题是如何处理连接。要创建连接,请运行查询并关闭连接-这非常糟糕。连接是昂贵的。它们也是有限的,所以您不想创建一百万个连接来执行逻辑

因此,您将使用某种连接池并将查询放入队列中

另外,我希望您使用的是绑定变量,而不是字符串连接来将查询传递给oracle


通常,我会收集所有数据(最好是一次查询),然后才更新对象。您也可以考虑将对象拖动到它的部分中。

线程工作完全。2年前,我做了一个项目,使用多策略/多线程方法将数据推送到oracle数据库中(并从中提取一些数据进行更新)

我基本上使用了一种分阶段的方法(一个请求将经过多个阶段,在那里被消费,新数据将被传送到下一个阶段),每个阶段都使用一个可配置的线程池,它将接收一条消息,处理它并发布新的消息

我想当时我们使用了将近200个线程,每分钟处理大约一百万条SQL语句(涉及到一个Oracle Exadata,它确实从中获得了一些工作)

因此,多线程“只起作用”——显然,如果您知道如何做到这一点,并且必须使您的体系结构和sql语句良好且无阻塞。一般来说,数据库完全可以处理多个线程

现在,关于细节:这要看情况而定

例如:

当前,其他查询将结果封送到不同的 同一对象的部分。这是否会导致任何问题(即 不过,我们正在不同线程中访问/更新同一对象 对象中的不同部分/字段?)

绝对没有问题,只要:

  • 在将对象移动到下一个阶段之前完成所有更新,然后
  • 更新没有重叠或基数(1必须完成,2才能获得所需数据)
这些都是实现细节,很难给出一个通用的答案(完全不可能)。特别是因为这是多线程101,与任何数据库访问无关


一般来说,您还必须调整线程的数量。NET本身无法做到这一点,因为它将看到CPU不忙,并生成更多线程,即使数据库服务器是瓶颈。这就是我们使用多个阶段的原因——因此我们可以根据线程的工作来调整线程的数量(最后一个阶段使用大容量插入将聚合数据插入到具有少量线程的临时暂存表中,在每个语句中移动大量数据-这将需要一些调整可能性,以避免数据库端完全过载).

我想知道这是否是一个XY问题。你确定有必要进行3-12次往返以获取有效的单个实体的数据吗?为什么数据以这样一种方式分布在你的层上,以至于你无法将其归结为单个查询?在IO问题上抛出线程通常没有那么好的效果。看起来他还没有绑定IO,是吗这在一定程度上是有帮助的。每个对象实例执行3到12个查询是否正确?通常从DB加载多少个对象(10010001000000,…)?你的意思是oracle提供程序太愚蠢了,他们没有实现C#/ADO.NET连接管理所必需的连接池?真的吗?否则打开一个新连接是非常便宜的。从v1开始,连接池在.NET中是标准的。@TomTom-你是说如果我尝试打开10^6个连接,我会得到一些po吗替换为ol?其中是一个边界,我的X连接将自动替换为Y(@TomTom-如果您的评论是关于自己不实现池的-100%同意。当您关闭连接时,它应该返回到标准池中。显示oracle连接字符串以及如何控制池大小。这是.NET中池连接的标准行为。感谢链接。我看到您可以指定使用池当连接到DB时,它将对应用程序透明。