.NET连接池的问题详解

NET 连接池救生员

防止可淹没应用程序的池溢出

William Vaughn

大多数 ADO.NET 数据提供程序使用连接池,以提高围绕 Microsoft 断开连接的 .NET 结构构建的应用程序的性能。应用程序首先打开一个连接(或从连接池获得一个连接句柄),接着运行一个或多个查询,然后处理行集,最后将连接释放回连接池。如果没有连接池,这些应用程序将花费许多额外时间来打开和关闭连接。

当您使用 ADO.NET 连接池来管理基于 Web 的应用程序和客户端/服务器 Web 服务应用程序的连接时,您的客户通常会获得更快的连接和更好的总体性能。但是,当您的应用程序或 Web 站点上突然涌入了同时希望进行连接的大量客户时,会发生什么事情呢?您的应用程序会“沉没”,还是会“游泳”?就像救生员一样,您需要仔细监视连接池,以维护它的良好性能,并防止连接池发生溢出。我们首先探讨连接池可能溢出的原因,然后讨论如何编写代码或使用 Windows 性能监视器来监视连接池。

正如我于 2003 年 5 月发表的 “Swimming in the .NET Connection Pool” (InstantDoc ID 38356) 一文中讨论的那样,当您使用连接池时,您需要知道许多有关可伸缩性和性能的详细信息。请记住,您需要监视和管理两个基本因素:每个池管理的连接数和连接池的数量。在一个有效的生产系统中,池的数量通常很少(1 到 10),而且,使用中的连接的总数也很少(少于 12 )有效的查询只用不到一秒钟的时间就可以完成,并断开连接。因此,即使有数百个客户同时访问您的 Web 站点,相对较少的几个连接常常足以处理整个负载。为了使您的应用程序有效地运行,您必须使连接资源处于自己的控制之下,并要监视池的状态,这样,在监视池发生溢出以及您的客户开始抱怨(或离开您的网站)之前您会收到某种警告。

为什么会发生连接池溢出?

GPS平台、网站建设、软件开发、系统运维,找森大网络科技!

参加电子邮件讨论组的人常常抱怨应用程序是如何在测试中是“龙”而在形成为产品时就变成了“虫”的。有时,他们会报告说,当连接了大约 100 个客户端时,应用程序会停止或挂起。请记住,一个池中的默认连接数是 100。如果您尝试从池中打开 100 个以上的连接,ADO.NET 会使应用程序的连接请求排队等候,直到有空闲的连接。应用程序(及其用户)将这种情况视为进入 Web 页的延迟或视为应用程序死锁。让我们首先讨论一下这个问题是如何产生的。

在 ADO.NET 中,SqlClient .NET 数据提供程序为您提供了两种打开和管理连接的方法。首先,当您需要手工管理连接时,可以使用 DataReader 对象。利用这种方法,您的代码将构造一个 SqlConnection 对象,设置 ConnectionString 属性,然后使用 Open 方法来打开连接。当代码完成 DataReader 后,您要在 SqlConnection 对象停止作用之前关闭 SqlConnection。要处理行集,您可以将 DataReader 传递到应用程序中的另一个例程,但仍然需要确保 DataReader 及其连接处于关闭状态。如果您不关闭 SqlConnection,代码会“泄漏”每个操作的连接,于是连接池对连接进行累积,最后便发生溢出。与 ADO 和 Visual Basic (VB) 6.0 中的情况不同,.NET 垃圾回收器不会为您关闭 SqlConnection 并进行清理。我稍后要讨论的 清单 1 显示了如何打开连接和生成 DataReader 以从一个简单的查询返回行集,来向连接池施加压力的。

您也可能在使用 DataAdapter 对象时遇到问题。DataAdapter Fill 和 Update 方法可自动打开 DataAdapter 对象的连接,并在数据 I/O 操作完成后关闭该连接。不过,如果该连接在执行 Fill 或 Update 方法时已经处于打开状态,那么,ADO.NET 在方法执行完以后不会关闭 SqlConnection。这是另一个发生连接“泄漏”的机会。

此外,您还可以使用基于 COM 的 ADO 从 .NET 应用程序创建连接。ADO 利用与 ADO.NET 相同的方式将这些连接组合成池,但不能像您使用 SqlClient ADO.NET 数据提供程序时那样,提供从应用程序监视连接池的方式。

指示 DataReader

孤立连接和溢出池是严重的问题,根据有关这些问题的新闻组讨论的数量来看,它们十分常见。这些问题最有可能是由 DataReader 引起的。为了测试 DataReader 的行为,我编写了一个 Windows 窗体 (WinForms) 示例应用程序,该示例突出了 CommandBehavior.CloseConnection 选项。(您可以在 http://www.sqlmag.com 上输入 InstantDoc ID 39031 来下载此应用程序)。您可以在使用 SqlCommand 对象的 ExecuteReader 方法来执行查询并返回 DataReader 时设定此选项。我的测试应用程序显示,如果不显式关闭 DataReader(或 SqlConnection),即使使用此选项,连接池还是会溢出。当代码所请求的连接数超过连接池的容量时,该应用程序就会引发异常。

有些开发人员坚持认为,如果您设置 CommandBehavior.CloseConnection 选项,则 DataReader 及其相关联的连接会在 DataReader 完成数据读取时自动关闭。这些开发人员的看法不完全正确 — 只有当您在 ASP.NET Web 应用程序中使用复杂的绑定控件时,该选项才以这种方式工作。在整个 DataReader 结果集中循环到其行集的末尾(也就是说,当 Dr.Read — DataReader 的 Read 方法 — 返回 False 时)还不足以触发连接的自动关闭。不过,如果您绑定到一个复杂的绑定控件(例如,DataGrid),该控件则会关闭 DataReader 和连接 — 前提条件是您设置了 CommandBehavior.CloseConnection 选项。

如果您通过使用另一个 Execute 方法(例如,ExecuteScalar、ExecuteNonQuery 和 Execute Reader)执行查询,则您需要负责打开 SqlConnection 对象,而且,更重要的是,在查询结束时关闭该对象。如果您忘记了进行关闭,孤立连接会迅速地积累起来。

监视连接数

为了对孤立连接和发生溢出的连接池进行测试,我编写了一个 Web 窗体的示例应用程序。此应用程序使用的方法与您通常用于从查询返回数据的方法相同。(您可以在 http://www.sqlmag.com 上下载此代码的 WinForms 版本。)

我使用了清单 1 中的代码来打开和关闭到 Web 窗体应用程序的连接。标注 A 中的例程针对 110 个新的 SqlConnection 对象创建、打开和执行查询 — 比默认的池大小多 10 个连接。您必须在离开该例程之前关闭和放弃所有这些连接。如果不这样做,SqlConnection 对象将连同关联的池连接一起被孤立。ADO.NET 池机制 (aka the Pooler) 关闭数据库连接,但不关闭池连接。我将连接池大小设置为 10,以便使该程序更快地失败 — 如果该程序会失败的话。通常,10 个连接对于一个运行速度象这个查询一样快的查询来说已经足够了。许多开发人员运行着忙碌的 Web 站点,这些 Web 站点使用不到五个连接来处理每天的几十万次点击。

标注 A 中的例程创建 SqlConnection 对象和 SqlCommand 对象,设置 CommandText,并打开连接。然后,标注 B 中的代码确定执行 DataReader 时是否使用 CommandBehavior.CloseConnection,这取决于用户在 Web 窗体上选择了哪些 CheckBox 控件。

在标注 C 的代码中,我指定是否将 DataReader 行集绑定到 DataGrid,或者是否在整个行集中进行循环。标注 C 的代码测试当您到达通过 DataReader 从数据提供程序传递回来的行集的末尾时会发生什么事情。

现在,我使用标注 D 中的代码来指定是手工关闭连接还是让某个其他操作(例如,数据绑定)来完成这项工作。坦白地说,以手工方式关闭连接通常是最安全的,因此,您可以肯定连接不会被孤立。

如果代码成功地运行到这一步,说明我已经成功地打开和关闭了 110 个连接。不过,如果出了问题,标注 E 的代码中的异常处理程序会将异常(通常是 Timeout)作为 InvalidOperationException 捕获,该异常是连接池已满时 ADO.NET 的响应方式。

表 1汇总了各个选项使例程成功运行或失败的方式。请注意,如果您不设置 CommandBehavior.CloseConnection 选项,您的操作最终会失败 — 即使在使用绑定控件的情况下也是如此。即使您使用该选项,但如果您没有使用复杂的绑定控件,或者没有手工关闭 SqlDataAdapter 或 SqlConnection,该进程仍然会失败。

当我结束了这些示例应用程序的运行后,我已经生成了 1000 多个以上的池连接 — 所有连接均处于孤立状态。虽然“SQL Server 用户连接”计数为 0,但留下大约 40 个连接池。在我重新引导系统之前,孤立的池不会消失。

我用于此测试的示例应用程序包括使用 DataAdapter 来返回行的例程。除非您手工管理连接,否则,DataAdapter 将正确地打开和关闭 SqlConnection 对象,因此,您不太可能遇到孤立的池连接。不过,如果您的应用程序同时使用 DataReader 和 DataAdapter,您可能会发现,如果某个连接与一个未关闭的 DataReader 相关联,则 DataAdapter 无法针对该连接运行查询。

确定连接池何时达到最大连接数

正如我在 “Swimming in the .NET Connection Pool” 一文中讨论的那样,当连接池达到您通过 “Max Pool Size ConnectionString” 选项指定的最大连接数时,ADO.NET 将阻止任何随后打开额外连接的尝试。如果某个连接在您在 "ConnectionTimeout 选项中指定的时间之前变为可用,.NET 数据提供程序将向您的应用程序传递一个指向该连接的指针,以便将控件返回给应用程序。不过,如果没有及时释放任何连接,连接请求将引发 InvalidOperationException 异常。

现在您必须决定要采取的措施,我不建议您告诉用户您已经用完了所有连接。有些应用程序会通知用户系统正忙于帮助其他客户,并建议用户稍后进行访问。其他应用程序则播放一段动画,通知用户系统尚未死锁,而是正在忙于处理他们的请求。同时,您的代码重新尝试操作。在所有情况下,您应该记录这些故障,以便帮助诊断问题的症结所在,并记录您已经耗尽了资源。

监视连接池

您已经打开和关闭了一个连接,现在您希望知道该连接是否仍然处于打开状态。您可以使用几种方法来确定有多少连接仍然处于打开状态,以及它们正在执行何种操作:

  • 运行 sp_who 或 sp_who2。这些系统存储过程从 sysprocess 系统表返回信息,该系统表显示所有工作进程的状态及其有关信息。通常,您会看到每个连接有一个服务器进程 ID (SPID)。如果您是通过在连接字符串中使用 Application Name 参数来命名您的连接的,那么,您将很容易找到工作的连接。
  • 使用带有 SQLProfiler TSQL_Replay 模板的 SQL Server 事件探查器来跟踪打开的连接。如果您很熟悉事件探查器,此方法比通过使用 sp_who 进行轮询要更容易。
  • 使用性能监视器来监视池和连接。我稍后再讨论此方法。
  • 在代码中监视性能计数器。您可以通过使用例程来提取计数器或通过使用新的 .NET PerformanceCounter 控件来监视连接池的状况和已建立的连接的数量。这两种方法都包括在您可以从 http://www.sqlmag.com 进行下载的示例应用程序中。

现在我们将讨论如何查找连接池计数器,以及如何使用这些监视方法。

连接池计数器在哪里? 要监视连接池计数器,您必须监视 ADO.NET 在其中创建和增加这些计数器的系统。如果您从远程系统进行连接,ADO.NET 并不总是在 Microsoft IIS 服务器或 SQL Server 上创建池;它在 ADO.NET 代码运行的系统上创建池。此系统可以是运行 IIS、Web 应用程序或 Web 服务的远程 Windows 或中间层系统。相反,SQL Server 性能计数器位于 SQL Server 系统上 — 而不是客户端上。

使用性能监视器来监视池。 如果您使用 Microsoft 管理控制台 (MMC) Windows 2000 系统监视器管理单元,则您可以通过从 Performance 对象下拉列表中选择 “.NET CLR Data” 来用图形表示 SqlClient 计数器,如 图 1所示。请注意,您可以通过选择 global 计数器实例来监视所有进程,或者,您可以查看某个特定实例 — 每个池生成自己的一组监视器。性能监视器可列出这些计数器,并将它们作为所选定的性能对象的实例提供。但性能监视器不会公开这些计数器,除非有实例需要它们进行监视。例如,图 1 显示了 .NET CLR Data 性能对象,但没有列出特定实例。这意味着您必须至少创建一个连接,以便使 global 实例连同每个进程的特定实例一起出现。这种行为对于您的代码来说是个问题;您将无法使用 PerformanceCounter 控件来返回其中的任何计数器,直到 ADO.NET 在打开连接时创建这些计数器。所以说,这个规定真有点令人左右为难。当您使用此方法时,因为缺少有效计数器实例,所以会引发异常 — 此时要准备好捕获异常。

您还可以通过使用 SQL Server 性能计数器 “User Connections” 来监视打开的连接的数量。该计数器被列在 Performance 对象下拉列表中的 SQL Server: General Statistics 下。我喜欢监视 “User Connections” 值和一些所选定的 .NET CLR Data SqlClient 计数器(我稍后将讨论此内容),因为我可以获得我需要的信息,而不必担心实例。

使用代码来监视性能计数器。 当您需要以编程方式监视连接池时,您可以编写代码来监视由 SqlClient 管理的性能计数器 — 这些计数器与 MMC Windows NT 性能监视器管理单元所提供的计数器是相同的。编写执行监视的代码似乎是一件有些令人畏惧的事情。但我已经提供了从 SqlClient 提供程序的内部工作提取这些计数器的例程的快照(作为本文提供的可下载程序之一)。

您可以编写检查 表 2显示的五个计数器的代码。通过利用这五个计数器,您可以实时监视连接池。.NET 预期您会在性能监视器中提供一个类别 — 复制的 Performance — 并从那些注册到系统的计数器中选择适当的计数器。要访问 SqlClient 计数器,请将该类别设置为 “.NET CLR Data”。

使用 PerformanceCounter 控件。 您可能会发现,在设计时向您的应用程序窗体添加 PerformanceCounter 要比手工编写代码来访问性能计数器更加容易。要使用 PerformanceCounter 控件,请从“Visual Studio .NET 工具箱组件”菜单中选择一个 PerformanceCounter,将它拖到您的应用程序窗体,然后设置属性,如 图 2 所示。这些控件工作在 Web 窗体和 WinForms 应用程序中。

因为 PerformanceCounter 控件提供了方便的下拉列表,所以,您可以在设计时看到任何一种性能计数器类别、计数器名称和特定实例 — 您将要运行的实例除外。这意味着您必须使用图 2 显示的方法来捕获应用程序正在使用的池的适当实例。为了回避这个问题,我选择 global 实例。再次说明一下,此方法假设某个应用程序已经至少创建了一个池,因此您需要做好不存在计数器实例时 ADO.NET 引发异常的准备,就像它在不存在池连接时也会引发异常一样。

注意不准确的池计数。 因为 SqlClient .NET 数据提供程序中存在 .NET 框架 1.1 尚未解决的错误,所以,性能计数器会在池实际上已经删除时错误地指示池“仍然存在”。我能通过结束 MMC 性能监视器管理单元、然后结束 Visual Studio .NET 来验证池已经不再存在。这些步骤说明,.NET 数据提供程序在创建连接池的进程结束时会正确地删除连接池。显然,这种不准确性降低了性能计数器在监视池方面的有效性,所以我希望 Microsoft 将来能解决这个问题。

计数器不显示的内容

您可能会面临的一个问题是无法从计数器或 SqlClient 属性看到每个池的配置。每个 SqlConnection 对象的 ConnectionString 保存着这些池设置的密钥。因为您不能依赖于默认设置,所以很难确定池几乎已满或很难使用。这会成为未来版本的 ADO.NET 的另一个方便功能。

不过,假设您知道各个连接池 ConnectionString 参数的值,则利用清单 1 中的代码,您可以很容易地设置一个计时器来检查您创建的特定池并报告使用百分比。然后,监视应用程序会向您发出警报,以便您可以解决问题并防止溢出。

最后,请记住,ADO.NET 采用的方法与基于 COM 的 ADO 有所不同。Visual Basic .NET 完全改变了放弃对象的方式,并且不再确保 Connection 对象在停止作用时被关闭。请确保 SqlConnection 对象(或任何 Connection 对象)在停止作用之前被关闭。

连接池是一种非常强大的功能,它可以提高应用程序的性能。但如果您不是一个出色的救生员,您的连接池会成为一个危害而不是一个优点。我希望本文讨论的方法有助于您有效地监视连接池并满足用户的需要。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ADO.NET数据连接池剖析

    本篇文章起源于在GCR MVP Open Day的时候和C# MVP张响讨论连接池的概念而来的.因此单独写一篇文章剖析一下连接池. 为什么需要连接池 剖析一个技术第一个要问的是,这项技术为什么存在. 对于每一个到SQL Server的连接,都需要经历TCP/IP协议的三次握手,身份认证,在SQL Server里建立连接,分配资源等.而当客户端关闭连接时,客户端就会和SQL Server终止物理连接.但是,我们做过数据库开发的人都知道,每次操作完后关闭连接是再正常不过的事了,一个应用程序即使在负载

  • .net 中的SqlConnection连接池机制详解

    正确的理解这个连接池机制,有助于我们编写高效的数据库应用程序. 很多人认为 SqlConnection 的连接是不耗时的,理由是循环执行 SqlConnection.Open 得到的平均时间几乎为0,但每次首次open 时,耗时又往往达到几个毫秒到几秒不等,这又是为什么呢? 首先我们看一下 MSDN 上的权威文档上是怎么说的 Connecting to a database server typically consists of several time-consuming steps. A

  • .NET 数据库连接池

    则您需要负责打开 SqlConnection 对象,而且,更重要的是,在查询结束时关闭该对象.如果您忘记了进行关闭,孤立连接会迅速地积累起来.监视连接数 为了对孤立连接和发生溢出的连接池进行测试,我编写了一个 Web 窗体的示例应用程序.此应用程序使用的方法与您通常用于从查询返回数据的方法相同.(您可以在 http://www.sqlmag.com 上下载此代码的 WinForms 版本.) 我使用了清单 1 中的代码来打开和关闭到 Web 窗体应用程序的连接.标注 A 中的例程针对 110 个

  • ADO.NET之连接池技术的使用详解

    连接到数据库服务器通常需要一定的时间,且服务器也需要一定的资源来处理连接.Web应用程序有时处理成千上万的连接,需要相当多的资源来处理连接.ADO.NET具有连接池的特性,连接池的功能是保留一定数量的连接,当用户使用相同的连接字符串再次连接服务器时,ASO.NET将使用连接池中的连接而不用重新发起一次连接过程.当调用Close方法关闭连接时,ADO.NET将使用连接池中的连接而不用重新发起一次连接过程.当调用Close方法关闭连接时,连接将会返回到连接池中,下次再次调用Open方法时,将从连接池

  • asp.net 数据库连接池浅析

    1,对于ASP.NET数据库连接池可以使用一组名称-值对以链接字符串的形式配置链接池.例如,可以配置池是否有效(默认是有效的),池的最大.最小容量,用于打开链接的排队请求被阻断的时间.下面的示例字符串配置了池的最大和最小容量. "Server=(local); Integrated Security=SSPI; Database=Northwind; Max Pool Size=75; Min Pool Size=5" ASP.NET数据库连接池摘要 连接池允许应用程序从连接池中获得一

  • .NET Framework SQL Server 数据提供程序连接池

    您也可以提供几个连接字符串修饰符来控制连接池行为,请参见本主题内下文中"使用连接字符串关键字控制连接池"这一节. 池的创建和分配 当连接打开时,将根据一种精确的匹配算法来创建连接池,该算法会使连接池与连接中的字符串相关联.每个连接池都与一个不同的连接字符串相关联.当新连接打开时,如果连接字符串不精确匹配现有池,则将创建一个新池. 在以下示例中,将创建三个新的 SqlConnection 对象,但只需要使用两个连接池来管理这些对象.请注意,第一个和第二个连接字符串的差异在于为 Initi

  • .net数据库连接池配置技巧(默认值)

    以连接字符串关键字控制Connection Pool ConnectionString属性是SQLConnection 对象的一个属性,它支持一个连接串/值对,这个对是用于调整connection pool行为的.下表是ConnectionString 的值及解释. 名称 默认值 描述 Connection Lifetime 0 当连接返回pool时,它的时间和创建时间相比,如果它的存在时间超过了Connection Lifetime,它被释放.这对于新加入集群的服务器平衡是很有用的.值0可以保

  • 数据库阿里连接池 druid配置详解

    Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,有不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色的性能,也逐渐印入了大家的眼帘.接下来本教程就说一下druid的简单使用. 首先从 http://repo1.maven.org/maven2/com/alibaba/druid/下载最新的jar包.如果想使用最新的源码编译,可以从 https://github.com/alibaba/druid下载源码,然

  • .NET连接池的问题详解

    NET 连接池救生员 防止可淹没应用程序的池溢出 William Vaughn 大多数 ADO.NET 数据提供程序使用连接池,以提高围绕 Microsoft 断开连接的 .NET 结构构建的应用程序的性能.应用程序首先打开一个连接(或从连接池获得一个连接句柄),接着运行一个或多个查询,然后处理行集,最后将连接释放回连接池.如果没有连接池,这些应用程序将花费许多额外时间来打开和关闭连接. 当您使用 ADO.NET 连接池来管理基于 Web 的应用程序和客户端/服务器 Web 服务应用程序的连接时

  • jdbc与druid连接池的使用详解

    使用jdbc实现对数据库的操作 Ⅰ 获取数据库连接 package org.example.utils; import java.sql.*; public class JavaDateConnection { /** * 获取数据库连接 * @return Connection */ public Connection getConn() { //project为数据库名 String url = "jdbc:mysql://localhost:3306/project"; //用户

  • Python3爬虫关于代理池的维护详解

    我们在上一节了解了代理的设置方法,利用代理我们可以解决目标网站封 IP 的问题,而在网上又有大量公开的免费代理,其中有一部分可以拿来使用,或者我们也可以购买付费的代理 IP,价格也不贵.但是不论是免费的还是付费的,都不能保证它们每一个都是可用的,毕竟可能其他人也可能在用此 IP 爬取同样的目标站点而被封禁,或者代理服务器突然出故障或网络繁忙.一旦我们选用了一个不可用的代理,势必会影响我们爬虫的工作效率. 所以说,在用代理时,我们需要提前做一下筛选,将不可用的代理剔除掉,保留下可用代理,接下来在获

  • Go创建Grpc链接池实现过程详解

    目录 常规用法 创建链接池 创建链接池接口 实现链接池接口 关闭链接 扩缩容 性能测试 常规用法 gRPC 四种基本使用 请求响应模式 客户端数据流模式 服务端数据流模式 双向流模式 常见的gRPC调用写法 func main(){ //... some code // 链接grpc服务 conn , err := grpc.Dial(":8000",grpc.WithInsecure) if err != nil { //...log } defer conn.Close() //.

  • 关于php几种字符串连接的效率比较(详解)

    php大致有三种字符串连接: 1.直接用.来进行连接. 2.用.=进行连接. 3.先压入数组,再通过join函数连接. 下面分别对这三种方法的效率进行测试: 第一种方法代码如下: <?php function get_tm() { list ( $usec, $sec ) = explode ( " ", microtime () ); return (( float ) $usec + ( float ) $sec); } $temp="test"; $re

  • Java 常量池的实例详解

    Java 常量池的实例详解 Java的常量池中包含了类.接口.方法.字符串等一系列常量值.常量池在编译期间就已经确定,并保存在*.class文件中 一.对于相同的常量值,常量池中只保存一份拷贝. 而且,当一个字符串由多个字符串常量链接而成时,多个字符串被组成一个字符串常量. 例如: package lxg; public class main { public static void main(String[] args) { String name = "lengxuegang";

  • java 打造阻塞式线程池的实例详解

    java 打造阻塞式线程池的实例详解 原来以为tiger已经自带了这种线程池,就是在任务数量超出时能够阻塞住投放任务的线程,主要想用在JMS消息监听. 开始做法: 在ThreadPoolExcecutor中代入new ArrayBlockingQueue(MAX_TASK). 在任务超出时报错:RejectedExecutionException. 后来不用execute方法加入任务,直接getQueue().add(task), 利用其阻塞特性.但是发现阻塞好用了,但是任务没有被处理.一看Qu

  • Hibernate迫切连接和普通连接的区别实例详解

    Hibernate 迫切连接和普通连接的区别 相关的介绍和解释在代码中已注释,大家可以参考. package com.baidu.test; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; i

  • 对Python中小整数对象池和大整数对象池的使用详解

    1. 小整数对象池 整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池, 避免为整数频繁申请和销毁内存空间. Python 对小整数的定义是 [-5, 256] 这些整数对象是提前建立好的,不会被垃圾回收.在一个 Python 的程序中,无论这个整数处于LEGB中的哪个位置, 所有位于这个范围内的整数使用的都是同一个对象.同理,单个字母也是这样的. In [1]: a=-5 In [2]: b=-5 In [3]: a is b Out[3]: True In [4]: a

随机推荐