目前,当我的网页首次加载时,我创建了一个数据库连接。然后,我处理页面并针对该连接运行任何查询。这是最好的方法还是应该在每次运行查询时都创建数据库连接?


我正在将C#(ASP.NET)与MSSQL配合使用。

#1 楼

如果您为每个查询/事务创建一个,则管理“关闭”连接要容易得多。

我可以理解为什么常识指示您应该打开一个并在整个过程中使用它,但是您将运行掉线和多线程问题。因此,您的下一步将是打开一个包含50个连接的池,并保持所有连接处于打开状态,并将它们分配给不同的进程。然后,您会发现这正是.NET框架已经为您完成的工作。

如果您在需要时打开连接并在完成后将其处理,那么实际上并没有关闭连接,它只会将其返回到连接池以再次使用。

评论


您链接到的网页特定于SQL Server。连接到其他数据库时,.NET是否还提供自动池化-例如Oracle,Sqlite,MySql?

– briddums
2012年3月29日18:32

@briddums:取决于提供程序程序集。我可以肯定,Microsoft的Oracle实现和Oracle自己的都支持连接池,因为我已经使用了它们。我听说有一个MySql可以做到,我希望Spring.NET中的提供程序支持池化,但是与直接询问或询问提供程序相比,最好不要问我。

– pdr
2012年3月29日18:50



应该知道,即使是在循环中,打开,运行查询和设置连接也要比一次打开并循环查询的速度一样快,有时甚至更快。总是处置。更安全,更快捷。不必担心从池中获得连接的开销,这很琐碎。

–smdrager
2012年10月2日17:33

@AlexVPerl:我需要进行分析并查看以下证据:a)实际节省的是不将连接返回到池,并且b)成本不是达到最大连接池的结果(原因是,如果这样做的话) ,那么任何节省都将意味着其他地方的费用-甚至可能是超时等待连接)。我还需要知道没有其他费用,例如呼叫之间的连接断开导致的问题。我还需要担心毫秒级的效率节省。一个不太可能的用例,但永远不要说永远。

– pdr
15年11月22日在16:12

MySQL Connector / Net支持连接池,以提高数据库密集型应用程序的性能和可伸缩性。默认情况下启用。

– Henka程序员
18年3月18日在18:25

#2 楼

最佳实践是为每个查询创建一个连接-在显示数据的情况下,最佳实践是让查询一次性带入所有需要的数据。

背景信息:

在.NET中,默认情况下,调用SqlConnection.Open()将始终透明地使用连接池(请参阅MSDN上的“在SQL Server中使用连接池”)。因此,您可以使用Open()捕获新连接,并在完成后调用Close(),.NET将做正确的事情。

请注意,如果没有连接池,则每个查询一个连接这是一个非常糟糕的主意,因为创建真实的数据库连接可能会非常昂贵(身份验证,网络开销等),并且同时打开的连接数通常非常有限。

评论


@webnoob-由于.​​NET使用连接池,因此不会。原因是连接可能会关闭,重新分配等-因此重用连接不是一个好习惯。

–奥德
2012年3月29日在9:51

-1答案颇具误导性。为每个查询创建连接是一个非常糟糕的主意。您可能的意思是“从连接池中为每个查询检索一个新连接”-但这与创建连接不同。

–sleske
2012年3月29日13:54

@sleske-与pdr的答案有何不同?

–奥德
2012年3月29日14:05

@Oded:啊,我明白了。在.NET中,调用SqlConnection.Open()将始终透明地使用连接池。因此,“打开连接”和“从池检索连接”之间不存在区别。我的误会我可以自由地在问题中添加一些解释,然后收回表决权。

–sleske
2012年3月29日14:28

@ eaglei22-它当然应该这样做(请参阅docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/…)。通常,您希望尽快将连接返回到池中,但是,如果按顺序发出许多查询,则按照您的建议重用连接可能会更好。您需要测试并查看哪种方法更适合您(我不知道您使用什么标准-两种方法都检查一下,并查看对所选指标的影响)。

–奥德
18年6月27日在13:08

#3 楼

开发人员有时希望“优化”他们的代码以重新使用他们的连接对象。考虑到此问题的上下文,我们进入了.Net生态系统,这几乎总是一个错误。 (请注意:许多其他平台也以类似的方式处理此问题。)ADO.Net具有称为连接池的功能。当您创建并打开一个新的连接对象时,您真正要做的就是从池中请求连接。关闭连接时,将其返回到池中。

理解我们直接在代码中使用的对象很重要:SqlConnection,MySqlConnection,OleDbConnection等都只是围绕真实基础连接的包装由ADO.Net管理。从性能的角度来看,ADO.Net的实际连接要“重”得多,而且要贵得多。正是这些底层对象担心身份验证,网络传输,加密等问题,而这些东西远远超过了您在自己的代码中实际看到的对象中的少量内存。

重新使用您的连接对象,您会在小事情上获得效率,而却要付出更大的代价,因为您破坏了ADO.Net连接池有效管理重要基础连接的能力。

在应用程序或http请求之间重新使用连接也可能会迫使您无意间序列化本来可以异步运行的操作,这些操作可能成为性能瓶颈。我已经在实际的应用程序中看到了这种情况。


在这里的网页示例中,您至少只在单个http请求/响应的持续时间内保持较小的连接,通过评估您在请求管道中运行的查询并尝试获取它们尽可能减少对数据库的单独请求(提示:您可以在单个SQL字符串中提交多个查询,并使用DataReader.NextResult()或检查DataSet中的不同表在它们之间移动)。

换句话说,与其思考最小化创建的连接对象的数量(通过为应用程序或http请求重新使用一个连接),不如考虑每次每次往返都要调用数据库。然后尝试通过最小化这些行程的数量来最小化连接的数量。这样,您就可以满足这两个目标。


但这只是一种优化。还可以优化程序员的时间,并获得有效的代码重用。开发人员不想一遍又一遍地编写相同的样板代码,只是想获得一个开放的,随时可用的连接对象。这不仅繁琐,而且是将bug引入程序的一种方式。

即使在这里,通常每个查询(或往返)建立一个连接仍然更好。您可以使用一些模式来避免重写相同的样板代码,同时仍然保持每次调用数据库一个连接的目标。这是我喜欢的一个示例,但还有许多其他示例。

评论


我参加这个聚会很晚,但是我认为这个答案涵盖了一些要点:)

–乔尔·科恩(Joel Coehoorn)
19-09-23在21:21

#4 楼

我个人通常会发现软件获得了一个连接(通常是在“幕后”),然后重新使用该连接,直到获得该连接的例程退出为止。我期望找到理由“改善”这一点。