Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 传统的DB单例连接效果不佳_Java_Jdbc_Query Performance - Fatal编程技术网

Java 传统的DB单例连接效果不佳

Java 传统的DB单例连接效果不佳,java,jdbc,query-performance,Java,Jdbc,Query Performance,我在java应用程序中使用单例数据库连接,下面是我的连接管理器类的代码: public abstract class DatabaseManager { //Static instance of connection, only one will ever exist private static Connection connection = null; private static String dbName="SNfinal";

我在java应用程序中使用单例数据库连接,下面是我的连接管理器类的代码:

public abstract class DatabaseManager {
    //Static instance of connection, only one will ever exist
        private static Connection connection = null;    
        private static String dbName="SNfinal";
        //Returns single instance of connection
        public static Connection getConnection(){       
            //If instance has not been created yet, create it
            if(DatabaseManager.connection == null){
                initConnection();
            }
            return DatabaseManager.connection;
        }   
        //Gets JDBC connection instance
        private static void initConnection(){           
            try{        
                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
                   String connectionUrl = "jdbc:sqlserver://localhost:1433;" +
                      "databaseName="+dbName+";integratedSecurity=true";

                DatabaseManager.connection =
                             DriverManager.getConnection(connectionUrl);        
            }
            catch (ClassNotFoundException e){       
                System.out.println(e.getMessage());
                System.exit(0);
            }
            catch (SQLException e){         
                System.out.println(e.getMessage());
                System.exit(0);
            }
            catch (Exception e){        
            }       
        }
    public static ResultSet executeQuery(String SQL, String dbName)
    {
        ResultSet rset = null ;
        try {
               Statement st = DatabaseManager.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
               rset = st.executeQuery(SQL);
               //st.close();
        }
        catch (SQLException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }
        return rset;
     }

    public static void executeUpdate(String SQL, String dbName)
    {
        try {
               Statement st = DatabaseManager.getConnection().createStatement();
               st.executeUpdate(SQL);
               st.close();
        }

        catch (SQLException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }
     }
}
问题是我的代码在开始时工作得很完美,但当时间过去时,它变得非常缓慢。是什么导致了这个问题?我如何解决这个问题? 在启动时,我的应用程序每秒处理20个查询,运行1小时后达到每秒10个查询,运行3天后达到每10秒1个查询!! 注:我的应用程序是一个单用户应用程序,通过数据库进行许多查询。 注意:下面是我在eclipse.ini中的JVM参数:

--launcher.XXMaxPermSize
512M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
512m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.6
-Xms500m
-Xmx4G
-XX:MaxHeapSize=4500m
不幸的是,数据库是远程的,我没有任何监控访问权限来了解那里发生了什么。

以下是我的用法示例:

String count="select count(*) as counter from TSN";
ResultSet rscount=DatabaseManager.executeQuery(count, "SNfinal");
if(rscount.next()) {
    numberofNodes=rscount.getInt("counter");
}
  • 虽然连接管理器会自动关闭
    语句
    结果集
    ,但如果您立即关闭它们会更好

  • 您的代码中没有任何其他内容会影响您的单线程任务,所以我打赌您的数据库中一定有错误。尝试找出是否有任何数据库锁定或列索引错误。还可以查看数据库查询状态,找出瓶颈所在

  • 是什么导致了这个问题?我如何解决这个问题

    这里的主要问题是
    executeQuery()
    方法。 您没有关闭
    语句
    ,我想您已经注释了行
    st.close()
    ,因为您需要打开
    ResultSet
    以便进一步处理。 我可以看出,您的想法是避免在应用程序中看到重复的JDBC代码,但这不是正确的方法

    规则是:关闭
    结果集
    ,然后关闭
    语句
    , 否则,您将无法正确地释放资源,并且您将面临所描述的问题

    关于如何正确关闭资源,您可以找到一个很好的解释(请记住,在您的情况下,您不需要 (关闭连接)

    编辑: 例如:

    试试看{
    语句st=DatabaseManager.getConnection().createStatement(ResultSet.TYPE\u SCROLL\u不敏感,ResultSet.CONCUR\u只读);
    ResultSet rsCount=st.executeQuery(count);//count=“选择count(*)作为TSN中的计数器”;
    if(rsCount.next()){
    numberofNodes=rscount.getInt(“计数器”);
    }
    }捕获(SQLE异常){
    //日志异常
    }最后{
    rsCount.close();
    圣克洛斯();
    }
    
    < /代码> 您应该考虑使用一个断开的结果集,如缓存行集

    CachedRowSet实现ResultSet,因此它的行为应该类似于ResultSet

    除了这些更改之外,我建议您使用池数据源来获取连接并关闭它们,而不是保留一个打开的连接

    或者,如果您不是java7、bonecp或c3po

    编辑:

    为了回答您的问题,这解决了您的问题,因为
    CachedRowSetImpl
    在使用时不会保持与数据库的连接。 这允许您在填充
    CachedRowSetImpl
    后关闭
    Resultset
    语句


    希望这能回答你的问题

    在类中使用@singleton即使对于单用户应用程序,我建议使用一个连接池(例如BoneCP)和一个非常小的池。只需获得一个连接并在完成后关闭它,池将处理检查连接、在连接打开很长时间后替换连接等。它还保护您的代码不受以前执行的未提交事务等的影响。实际上,我需要尽可能快地运行查询。我第一次使用c3p0,但它在我的应用程序中的性能确实不如传统的单例连接(大约慢90%)。为什么您的
    st.close()
    被注释掉了?您是否正确地关闭了
    结果集
    ?在正确处理资源时,JDBC并不容易使用。我建议您使用像SpringJDBC及其
    JdbcTemplate
    这样的包装器库。此外,您关于连接池速度慢的论点似乎有点奇怪。当涉及到DB通信时,一些方法调用开销是微不足道的。但我同意,如果您的用例不需要连接池,就不需要它。您可能缺少的唯一优势是连接验证。我无法关闭结果集或语句,因为我要运行多个查询。当我关闭它们时,我得到了错误。分配的内存没有满,所以不可能是内存问题。我认为这是由其他原因引起的,但我不知道是什么原因。我坚持认为您的executeQuery()方法设计得不好。尝试进行一些重构,以便关闭语句。我不知道你的应用程序代码,但它应该很容易替换每个DatabaseManager.executeQuery()方法调用,用于树语句(1->get Connection,2->create Statement,3->get ResultSet),允许你关闭结果集,尤其是语句。我添加了一个如何调用此方法的示例,请您解释一下您对这个示例的想法好吗?在我的代码的所有部分中更改它确实很耗时,所以我选择了Summit解决方案。我想知道为什么这个解决方案完全解决了我的问题!!如果是数据库问题,为什么它应该随着时间的推移而扩展?因为您的数据集在不断增长,查询100M记录肯定比100K记录慢。不,它没有增长,我一个记录一个记录地执行查询过程!请问为什么这个解决方案解决了我的问题?!我监控了这两种方法中的jvm资源使用情况。从资源管理的角度来看,默认方法似乎更好,因此它不会因为资源的高使用率而导致!!
    public static ResultSet executeQuery(String SQL, String dbName)
    {
        CachedRowSetImpl crs = new CachedRowSetImpl();
        ResultSet rset = null ;
        Statement st = null;
        try {
               st = DatabaseManager.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
               rset = st.executeQuery(SQL);
               crs.populate(rset);
        }
        catch (SQLException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }finally{
            rset.close();
            st.close();
        }
        return crs;
     }