【发布时间】:2010-12-14 23:37:12
【问题描述】:
需要有关创建数据库连接池的信息(与数据库无关),以及它们的效率如何?它们可以提高性能的条件是什么。
如何显式创建?
【问题讨论】:
标签: database connection connection-pooling
需要有关创建数据库连接池的信息(与数据库无关),以及它们的效率如何?它们可以提高性能的条件是什么。
如何显式创建?
【问题讨论】:
标签: database connection connection-pooling
Apache DBCP 的介绍页面总结得很好:
为每个人创建一个新的连接 用户可能很耗时(通常 需要多秒的时钟 时间),以执行数据库 可能需要的交易 毫秒。每打开一个连接 用户可能是不可行的 公共托管的互联网应用程序 其中同时用户数 可以很大。因此, 开发人员经常希望分享一个 所有开放连接的“池” 应用程序的当前用户。 实际用户数 在任何给定时间执行请求 通常是很小的百分比 活跃用户总数,以及 在请求处理期间是唯一的 数据库连接的时间 必需的。应用程序本身记录 进入 DBMS,并处理任何用户 内部帐户问题。
它们的效率如何?取决于实施。通常,我希望池在启动时或请求时实例化连接。第一个连接需要到数据库的真实连接,然后当您请求连接时,您将获得一个现有的池连接。因此,第一个连接请求将花费最多时间,之后您只是从集合中提取对象(非常快)。
【讨论】:
创建与数据库的连接是非常昂贵的操作。连接池是创建和缓存的数据库连接的实例。每当需要到数据库的新连接时,都会使用池中的一个,而不是创建新连接。 .NET + SQL Server 等一些平台默认使用连接池(您不需要创建自己的)。因此,它们基本上通过节省每次创建新连接的时间来提高性能。
【讨论】:
使用连接池可以节省每次访问的时间,因为连接已经建立。
而且,至少在 Oracle 上,您将编译后的语句与连接保持联系,因此重复执行相同的 SQL 语句会更快。
(如果您使用 Java/JDBC,请参阅 PreparedStatement)
反性能的唯一风险是当您在池中保留太多空闲连接时,相关的资源(您端和数据库上)会被浪费。
【讨论】:
创建数据库连接可能是一项昂贵的操作,也可能不是一项昂贵的操作,具体取决于您的环境以及您打算如何使用它。
如果您要运行一个非常简单的查询,那么连接可能需要与查询一样长(或更长)的时间。
某些数据库的连接开销比其他数据库大得多;如果调整正确,mysql 应该很少(超过建立 tcp 连接和进行协议握手的时间)。但是,如果您的服务器的延迟非常高,即使这也可能非常重要(特别是如果您打算只执行几个查询)。
如果您打算执行 100 个查询,或者一些非常慢的查询,那么连接时间就会变得微不足道。
通常我会说每次都打开一个新连接,直到您可以证明这是一个真正的性能问题。使用连接池可能会导致 BUGS,这是我们不喜欢的:
【讨论】:
查看基准部分中的 BoneCP (http://jolbox.com) 中的一些数字。请记住,preparedStatements 等与连接相关联,因此如果您自己处理连接,则需要一次又一次地准备它们(连接池也会为您缓存这些)。
到目前为止我最好的解决方案:使用一个lazyDataSource,它只在你真正需要它时给你一个连接(即不盲目 - 如果数据可以来自缓存,那么你可以避免数据库命中)
【讨论】:
你的问题有点含糊:
你想homegrow一个连接池实现吗?如果是这样,这是一个很好的起点:http://java.sun.com/developer/onlineTraining/Programming/JDCBook/conpool.html 但是这对于生产环境是非常不鼓励的。最好使用现有且经过全面测试的连接池 API,例如 DBCP 或 C3P0。
或者您想知道如何使用连接池?如果是这样,答案取决于您使用的连接池 API。幸运的是,它通常可以在相关 API 的网站上找到。
或者您想知道何时/为什么使用连接池?如果是这样,如果您有一个长期存在的应用程序(例如 web 应用程序)并且您需要经常连接数据库,它肯定会提高连接性能。正常的 JDBC 做法是:在 最短 可能的范围内(即在相同的方法块内)获取 和 .因为连接相当昂贵并且可能需要 200 毫秒甚至更多的时间,所以使用连接池要快得多。它按需提供连接并负责实际关闭连接。然而,这并不意味着你可以改变你编写 JDBC 的方式,你仍然需要在最可能的范围内获取和关闭它们。您唯一需要更改的是获取连接的方式。例如。从改变
connection = driverManager.getConnection();
到
connection = connectionPool.getConnection();
只要您的 JDBC 代码写得好,就不需要再做任何更改。
【讨论】:
使用tomcat创建数据库连接池
1. Tomcat进入资源里面:conf/context.xml
将资源条目放在 context.xml 文件中:
<!-- jdbc/jndiName jndi -->
<Resource name="jdbc/jndiName" auth="Container" type="javax.sql.DataSource" initialSize="1" maxActive="100" maxIdle="30" maxWait="10000" username="enter username" password="enter password" driverClassName="diver name" url="jdbc database url"/>
2。创建一个将创建连接池的类
public class MyConnectionFactory {
private static String module = "[ QuoteConnectionFactory ]";
private static QuoteConnectionFactory connectionFactory;
protected QuoteConnectionFactory() {
}
/**
*
* @return=>getInstance() is a static method which will return the instance
* of its own class
*/
public static QuoteConnectionFactory getInstance() {
if (connectionFactory == null)
connectionFactory = new QuoteConnectionFactory();
return connectionFactory;
}
/**
*
* @param jndiName
*/
public Connection getConnection(String jndiName) {
System.out.println("jndiName=======" + jndiName);
Connection conn = null;
InitialContext cxt = null;
DataSource dataSource = null;
try {
cxt = new InitialContext();
Context envContext = (Context)cxt.lookup("java:/comp/env");
dataSource = (DataSource)envContext.lookup(jndiName);
} catch (NamingException e) {
} catch (Exception e) {
}
if (dataSource == null) {
try {
conn = dataSource.getConnection();
} catch (Exception e) {
}
System.out.println("connection===================" + conn);
return conn;
}
}
3.编辑 web.xml 文件
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/jndiName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
4.在代码中使用
Connection con= QuoteConnectionFactory.getInstance(). getConnection("jndiName");
【讨论】: