JDBC yi daha performanslı nasıl kullanabiliriz?

'HTML-PHP-ASP-JAVA' forumunda Mavi_Sema tarafından 18 Mayıs 2009 tarihinde açılan konu

  1. Mavi_Sema

    Mavi_Sema Özel Üye

    Sponsorlu Bağlantılar
    JDBC yi daha performanslı nasıl kullanabiliriz? konusu JDBC (Java Database Connectivity) Java nın veritabanına ulaşmak için kullandığı standard API ye verilen addır.JDBC nin etkin kullanımı genel performansı önemli ölçüde etkileyen parametrelerdendir.Aşağıda JDBC hakkında dikkat edilmesi gereken birkaç noktaya değinmeye çalıştım :

    1) Veritabanına olan bağlantıyı sağlamak için DataSource kullanmalıdır.
    JDBC 2.0+ DataSource u desteklemektedir.DataSource objelerinin konfirigasyonu J2EE container ı üzerinde yapılır, veritabanı bağlantısını sağlar ve yönetir, pool mekanizması ve transaction desteği sağlar.
    Eskiden kullanılan yönteme örnek verelim :

    Class.forName(“oracle.jdbc.driver.OracleDriver”);
    DriverManager.getConnection(“jdbcracle:thinhos tort:sid”,username,pwd);

    Bu DataSource ile birlikte şu şekilde yapılmalıdır :

    InitialContext ctx = new InitialContext();
    DataSource ds = (DataSource) ctx.lookup(“java:comp/env/jdbc/OracleDS”)
    Connection conn = ds.getConnection();

    Not : OracleDS , burada veritabanının adıdır.Uygulama, “ejb-jar.xml” dediğimiz xml dosyasına InitailContext in lookup metodu ile bakar.Karşılığı olan “connection pool” u bulur ve bu pool üzerinden veritabanı bağlantısını kurar.

    2) Veritabanı bağlantılarını pool mekanizması üzerinden yapılmalıdır.
    Veritabanı’e klasik fiziksel bağlantı kurmak ve bunun üzerinden işlem yapmak maliyetlidir.Connection pool ile kurulan bağlantılar tekrar tekrar kullanılabilir.Ama diğer türlü ,bir bağlantı kurulur ve işlem bitince sonlanır.Pool mantığında ise aynı bağlantı tekrar tekrar kullanılabilir.Pool tanımları application server üzerinde yapılır.

    3) Mümkün olduğunca PrepairedStatement kullanılmalıdır.
    Veritabanı bağlantısını sağladıktan sonra artık veritabanında işlemler yapmaya başlayabiliriz.Bunu “statement” dediğimiz objelerle sağlarız.3 çeşit statement objesi vardır :

    statement
    preparedStatement
    CallableStatement

    “Statement” ve “preparedStatement” ile SELECT,UPDATE gibi temel SQL leri calıştırırken “CallableStatement” ile veritabanı de bir fonksiyon ya da procedure cağırmak için kullanırız.
    Statement ile prepairedStatement arasındaki fark , 2.nde bir kere derleme olur ve belirtilen parametreleri girmek suretiyle SQL’in tekrar tekrar kullanılması sağlanır.Bu da performasnı arttırır.1.de ise her çağrılma durumunda derleme işlemleri her seferinde tekrarlanır.Örnekler :
    Statement stmt = con.createStatement();

    ResultSet rs = stmt.executeQuery(”SELECT a, b, c FROM Table”);

    PreparedStatement pstmt = con.prepareStatement(
    “INSERT INTO EMPLOYEES (NAME, PHONE) VALUES (?, ?)”);
    pstmt.setString(1, theName);
    pstmt.setString(2, thePhone);
    pstmt.executeUpdate();

    4) Kullandıgımız herhangibir kaynağı işimiz bitince kapatmalıyız.
    Kullandıgımız kaynak connection olsun, ResultSet olsun, statement lardan biri olsun işimiz bitince kapatılmalıdır.Bunu try-catch bloğundan sonraki finally bloğu ile sağlayabiliriz.
    ResultSet rset = null;
    PreparedStatement pstmt = null;
    Connection conn = null;

    try {

    }
    catch(Exception e) {

    }
    finally{
    if(rset!=null)
    rset.close();

    if(pstmt!=null)
    pstmt.close();

    if(conn!=null)
    conn.close();
    }

    5) AutoCommit özelliğini control altında tutmalıdır.
    JDBC ile sağlanan veritabanı bağlantıları varsayılan olarak “autocommit”tir.Yani yapılan her DML işlemi sizin isteğiniz dışında commit lenir.Bu hem istenmeyen durumlara yol açar hem de çok sık commit etmenin oluşturacğı olası performans kayıplarına yol açabilir:

    pstmt.setLong(1,2345);
    pstmt.setString(2,”Sam”);
    pstmt.execute(); à COMMIT
    pstmt.setLong(1,2346);
    pstmt.setString(2,”Steve”);
    pstmt.execute();à COMMIT
    pstmt.setLong(1,2347);
    pstmt.setString(3,”Scott”);
    pstmt.execute();à COMMIT

    Bunu engellemek oldukça kolaydır.Yapılması gereken tek şey DML işlemlerimiz başlamadan autocommit özelliğini kapamak ve işlem bitince kendimizin commit etmesidir.Yani :

    connection.setAutoCommit(false);
    pstmt.setLong(1,2345);
    pstmt.setString(2,”Sam”);
    pstmt.execute();
    pstmt.setLong(1,2346);
    pstmt.setString(2,”Steve”);
    pstmt.execute();
    pstmt.setLong(1,2347);
    pstmt.setString(3,”Scott”);
    pstmt.execute();
    connection.commit();

    6) Tekrarlanan Batch işlemler için statement batching kullanılmaldır.
    Diyelimki devamlı sekilde bir insert yapıyoruz, bunu da preparedStatement ile yaptık.Her seferinde derlem olmuyor aynı SQL tekrar tekrar kullanılabiliyor.Bu uygulamamızı daha da performanslı yapmanın yolu var.Diyelim 10 tane insert yapılacak.Bunu 10 kez veritabanına gidip yapmak mıdır yoksa 10unu birden tek seferde gidip yapmak mıdır? Elbette 2.si.JDBC bu konuda da esneklik sağlıyor.Aşağıdaki gibi bir değişiklikle bu tip işlemlerimizin batch seklinde yapılmasını sağlayabiliriz :

    PreparedStatement pstmt = null;
    pstmt = conn.prepareStatement(”insert into emp(empno,ename) values(?,?)”);
    pstmt.setLong(1,101);
    pstmt.setString(2,Ahmet);
    pstmt.addBatch();
    pstmt.setLong(1,102);
    pstmt.setString(2,Alperen);
    pstmt.addBatch();

    int resultValues[] = pstmt.executeBatch();
    // examine resultValues[] to see status of
    // each batch operation

    7) ResultSet i gereğinden fazla şişirmemelidir.
    Örnegin 30 kolonlu bir tabloda bir işlemimiz için sadece 4 kolona ihtiyacımız var iken “select *” kullanmak gereksiz kaynak tüketmeye ve performans kaybına yol açacaktır.
    “select *” haliyle calistirildığı anda network üzerinde giden gelen veri büyüklüğü ile 4 kolounu veri büyüklüğünü karşılaştırmak konuyu daha iyi anlamamızı sağlayacaktır.

    Bunların yanında aşağıdaki noktalara da dikkat etmekte fayda var :

    Kolon ve satir bazında cekilen data miktarını azaltmak ya da arttırmak performansı etkiler.Bunu kontrol etmek için Statement objesinin setMaxRows, setMaxFieldSize, and SetFetchSize metodlarından faydalanılır.

    ResultSet ile değer alırken getObject metoduyerine alacağımız verini tipinde bir get metodu kullanmak daha performanslı olacaktır.(getInt(), getString() gibi)

    Yine ResutSet ile kolon bilgilerini alırken kolonların adını kullanmak yerine select teki sırasına göre kullanmalıdır.(rs.getString(1) gibi)
     
  2. avatar

    avatar Üye

    Eline sağlık paylaşım için sağol
     

Bu Sayfayı Paylaş