1

I'm using JDBC to query postgres database in my WebApp deployed in Apache Tomcat. Priority for the project is performance, that's why I decided to use JDBC. The app will have to handle multiple requests at the same time.

I am creating my connection in Spring configuration:

@Bean
public Connection connection() throws SQLException, ClassNotFoundException
{
    LOG.info("Creating JDBC connection...");
    Class.forName(this.dbDriver);
    return DriverManager.getConnection(this.dbUrl, this.dbUsername, this.dbPassword);
}

which is then injected into DAO and reused everytime.

I also have second implementation of the DAO that uses Hibernate, but it is much slower.

Questions:
- Will this solution scale? I.e. will it be fast, when for multiple requests at the same time? Does JDBC connection support concurrent requests or will it block on each request?
- Should I use some Tomcat's connection pooling mechanism (which?) to support concurrency? Or can I implement some connection pooling myself?

EDIT: I forgot to add: DB is read-only and I don't want blocking.
EDIT2: To clarify: I'm not opening and closing connections. I keep 1 connection open all the time.

FazoM
  • 4,777
  • 6
  • 43
  • 61
  • While I understand that performance is a priority for you, "Premature optimization is the root of all evil." You will probably *not* improve performance by reinventing the wheel. Minimizing framework use *may* result in better performance, but the speed of your call stack will likely be dwarfed by the wait time for the database to service your query. – Ian McLaird Oct 28 '15 at 14:33
  • Your 1-connection strategy is going to cause all kinds of havoc, unless this is a read-only application. Is your JDBC driver's connections thread-safe? – Christopher Schultz Oct 28 '15 at 14:50
  • 2
    Sorry, this is a bad design that won't scale. JDBC drivers are not required to be thread safe. You have a profound misunderstanding of how to write a performant application. – duffymo Oct 28 '15 at 14:55
  • Performance is tricky business. You're asking so many questions that I would suggest hiring outside help if possible. – Kayaman Oct 28 '15 at 14:56
  • @duffymo: i'm vaguely recalling i went around on this previously with somebody a long time ago, about whether jdbc drivers were required to be threadsafe, iirc it is in the spec that they should be. too lazy to look it up now, though. not that that makes it a good idea, of course. threadsafety for the connection is more for the benefit of the jdbc driver developers than for the clients, which should use thread-confined connections. can't stress enough how misguided the OP's one-connection statement is. OP: all your instincts about performance problems seem off-target. – Nathan Hughes Oct 29 '15 at 13:59
  • JDBC classes aren't required to be thread safe. Java EE containers have been written to handle threading from day one. Misguided, indeed. – duffymo Oct 29 '15 at 14:01
  • wow, thank you for clarifications on how I am profoundly misguided and misunderstanding! I asked the question to clarify this (see questions part: "Does JDBC connection support concurrent requests?") and you keep divulge how miss-guided I am. – FazoM Oct 29 '15 at 14:07
  • 1
    Go fix your code and stop whining. – duffymo Oct 31 '15 at 12:38

4 Answers4

4

Here are some answers that you might find helpful:

  1. Simply using JDBC isn't a guarantee of performance or scalability. Depends more on your schema, indexing, queries, data sets, etc.
  2. This is a poor way to create a database connection. It's not even correct Spring. Read up on how to configure Spring properly. When you call new or use getConnection Spring is not involved. Let the bean factory do this.
  3. A better idea is to set up a JNDI connection pool on Tomcat and configure Spring to use it.
  4. JDBC will block on each request. That's a good thing.
  5. Use what Tomcat will provide. You won't improve on existing connection pool implementations; it's likely you'll do far worse.
duffymo
  • 305,152
  • 44
  • 369
  • 561
  • Thanks for you input, please see my edit. I didn't want to use Spring, because I don't want any performance overhead. – FazoM Oct 28 '15 at 14:42
  • 1
    Sorry, you're just wrong. Use Spring. They are must smarter than you and me. If you have performance issues it'll be due to your code, not Spring. – duffymo Oct 28 '15 at 14:43
  • 1
    What does #4 "JDBC will block on each request" mean? – Christopher Schultz Oct 28 '15 at 14:49
  • A call to a JDBC connection is request/response. You'll wait for the response to come back. It blocks. – duffymo Oct 28 '15 at 14:52
  • I guess it blocks the connection, but I will have multiple requests at the same time. DB is read-only. (but it won't block the thread?) That's why I asked the question about what Tomcat and connection pooling can offer me. – FazoM Oct 28 '15 at 15:05
  • Tomcat queues up requests as they come in. Each servlet should be written as if it were single threaded. Tomcat handles the necessary behavior for each request being handled individually. – duffymo Oct 28 '15 at 15:06
3

Will this solution scale? I.e. will it be fast, when for multiple requests at the same time? Does JDBC connection support concurrent requests or will it block on each request?

IT won't, if each request create db connection, query the database, close the connection, Then it would slow as making db connection is costly operation.

JDBC tries to create connection per request/thread which would be blocked but after creation requests would be concurrent. But This would surely get connection resource crunch on higher amount of concurrent request.

Should I use some Tomcat's connection pooling mechanism (which?) to support concurrency? Or can I implement some connection pooling myself?

There are plenty open source JDBC connection pool library available, no need to reinvented the same wheel. Example - BoneCP, C3p0, DBCP, HikariCP etc.

References:

Community
  • 1
  • 1
Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
  • 1
    I couldn't agree more: get the connection, use the connection, close the connection the smallest method scope possible. Close resources in a finally block. Or just use Spring JDBC template. It's must smarter about this than we are. – duffymo Oct 28 '15 at 15:08
2

"Priority is performance" is vague, you should clarify what performance criteria are needed. "Multiple requests at the same time" doesn't sound extreme at all, and by itself isn't grounds for ruling out using a framework like Spring.

At some point Spring will incur some overhead. The most significant overhead would come from AOP, where the infrastructure can add a lot of layers of method calls to whatever you're doing. But this is a concern only for extremely high performance applications, you are a very long way from that point. A web application using Spring running in Tomcat should have no problem handling hundreds of concurrent connections.

Tomcat creates a pool of threads and allocates a thread to each request. When you setup Spring with a datasource that uses a connection pool, and you create DAOs that use JdbcTemplate, Spring assigns a database connection from the connection pool to the thread as a threadlocal. JDBC blocks, but only the thread making the query is affected, other requests can still execute independently, each on their own thread.

Using a single connection is a very bad idea. Typically connections are internally synchronized so that only one query can run at a time (if not for compliance with a spec, it would only make sense for them to be designed this way for protection from misuse by badly-behaved clients), your requests will have to wait to get access to the shared connection, your application won't be able to execute queries concurrently and performance will be miserable. If that's not enough, your application's resilience will be impacted, any network glitch or database downtime will cause your connection to go bad, and with no ability to renew the connection your application will stop working until it's restarted. Your first priority should be using a connection pool (an existing one). The connection pool will manage its connections, it can test them to make sure they're valid and replace stale ones with new connections, so you don't have to restart to recover from a network problem.

Next tune your queries, make sure they are efficient and are using indexes. There's no reason not to use spring-jdbc instead of raw JDBC, it reduces the cut-n-pasting that accompanies JDBC and adds great features like named query parameters and data access exception translation.

After that, introduce some kind of caching. There are a lot of ways to do this, depending on how up-to-date and consistent the data has to be, where you want the cache to live, and how extreme a performance benefit you really need. You can have caching going on at multiple levels, the database will cache results from recently-run queries, you can put a webserver in front of your application that caches GET requests. Spring introduces a cache abstraction so you can manage caching separately from application code.

Application-instance-level caching can be tricky, because it can interfere with resilience and scalability concerns. You may want to deploy your application in a cluster or otherwise as multiple instances in order to avoid making the server a single point of failure. In particular avoid using the HttpSession for anything but the bare minimum. Session changes either have to get propagated across cluster nodes, which creates more communication traffic as the number of nodes increases, or requests have to get pinned to a single server, reducing resilience (for these users the instance they're pinned to is now a SPOF again) and hurting load-balancing. If this is a read-only application then this will likely not be a concern, you should be able to do some aggressive caching. You could even consider having a dedicated database with tables that map to your views that are loaded from your original datasource, so the queries don't have to do joins and don't have any contention with what other applications may be doing.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
1

You'd better use technology such as database connection pool. Open connection and close connection takes time and consume resources.

In the java world, there are several db pool implementation, you don't need to reinvent the wheels.

You can useApache DBCP.

Here is the some introduction you can read http://www.snaq.net/java/DBPool/

buqing
  • 925
  • 8
  • 25
  • Thanks. I am not opening and closing connection. I keep 1 connection opened all the time. – FazoM Oct 28 '15 at 14:42
  • 2
    If you are using only one connection, the query will block until the result for the previous query returns.

    If you want to support multiple requests at the same time and don't want each one to wait for another, you'd better use multiple connection.

    can I ask a question? why do you want to use only 1 connection?

    – buqing Oct 28 '15 at 15:03
  • I was looking for simplest, working solution and I was thinking that I will avoid overhead of opening/closing connections. Today I thought about scalability and asked the question. – FazoM Oct 28 '15 at 15:09