JDBC 테스트 소스

POSTGRESQL 2015. 6. 24. 15:07

postgreSQL JDBC 접속테스트 소스입니다.

 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
 
public class JDBCExample {
 
 public static void main(String[] argv) {
  Connection conn = null;
  Statement  st   = null;
  ResultSet  rs   = null;

// connection 속성 설정
  String     url      = "jdbc:postgresql://localhost/postgres";
  String     user     = "postgres";
  String     password = "postgres";
  String    query    = "select version()";

  System.out.println("-------- PostgreSQL JDBC Connection Testing ------------");
  
  try {
// postgresql 드라이버 클래스를 JDBC드라이버 메니저에 로드
   Class.forName("org.postgresql.Driver");
 
  } catch (ClassNotFoundException e) {
 
   System.out.println("Where is your PostgreSQL JDBC Driver? "
     + "Include in your library path!");
   e.printStackTrace();
   return;
 
  }
 
  System.out.println("PostgreSQL JDBC Driver Registered!");
 
  //Connection conn = null;
 
  try {
// conncetion establish 하기
   conn = DriverManager.getConnection(url, user, password);
 
  } catch (SQLException e) {
 
   System.out.println("Connection Failed! Check output console");
   e.printStackTrace();
   return;
 
  }
 
  if (conn != null) {
   System.out.println("Connection established!");
  } else {
   System.out.println("Failed to make conn!");
  }

// 실행할 쿼리 statement 입력
  try { 
   st = conn.createStatement();
   rs = st.executeQuery(query);
   while (rs.next()) {
    String ver = rs.getString("version");
    System.out.println("Your version : " + ver);
   }
  } 
  catch (SQLException e ) {
   System.out.println("query execution failed...");
   e.printStackTrace();
                        return;
  } 
  
// statement / connection close 하기
  try {
   if (st   != null) { st.close(); }
   if (conn != null) {conn.close(); }
  }
  catch (SQLException e ) {
                        System.out.println("failed to close statement or connection");
                        e.printStackTrace();
                        return;
                }
 } //main end
}// JDBCExample class end

pg_trgm 을 이용한 전후위 like 검색

POSTGRESQL 2015. 4. 21. 17:12

하나의 컬럼에 대한 전후위 like 검색 시 인덱스 여부와 상관없이 table full scan 을 수행하는데 postgresql 은 pg_trgm 이라는 contrib 모듈을 통해 해결할 수 있습니다.

 

모듈 설치 전 실행계획입니다. 인덱스를 포함하는 컬럼에 대해 전후위 like 검색에 대하여 full scan을 수행합니다.

testdb=# explain analyze select * from test_table where test_column like '%TEXT%';
                                                     QUERY PLAN                                                      
---------------------------------------------------------------------------------------------------------------------
 Seq Scan on test_table  (cost=0.00..288431.08 rows=264 width=298) (actual time=952.905..1119.831 rows=6 loops=1)
   Filter: ((test_column)::text ~~ '%TEXT%'::text)
 Total runtime: 1119.854 ms
(3 rows)

 

contrib 모듈을 설치하고 해당 컬름으로 GIN INDEX를 생성합니다.
$ make && make install
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I. -I. -I../../src/include -D_GNU_SOURCE   -c -o trgm_op.o trgm_op.c
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I. -I. -I../../src/include -D_GNU_SOURCE   -c -o trgm_gist.o trgm_gist.c
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I. -I. -I../../src/include -D_GNU_SOURCE   -c -o trgm_gin.o trgm_gin.c
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -shared -o pg_trgm.so trgm_op.o trgm_gist.o trgm_gin.o -L../../src/port -Wl,--as-needed -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags  
/bin/mkdir -p '/usr/local/pgsql/lib'
/bin/mkdir -p '/usr/local/pgsql/share/extension'
/bin/mkdir -p '/usr/local/pgsql/share/extension'
/bin/sh ../../config/install-sh -c -m 755  pg_trgm.so '/usr/local/pgsql/lib/pg_trgm.so'
/bin/sh ../../config/install-sh -c -m 644 ./pg_trgm.control '/usr/local/pgsql/share/extension/'
/bin/sh ../../config/install-sh -c -m 644 ./pg_trgm--1.0.sql ./pg_trgm--unpackaged--1.0.sql  '/usr/local/pgsql/share/extension/'
$ psql -p 5433 -d testdb -U pgdba
psql (9.2.8)
Type "help" for help.
testdb=# create extension pg_trgm;
CREATE EXTENSION
testdb=# CREATE INDEX trgm_idx ON test_table USING gin (test_column gin_trgm_ops);
CREATE INDEX

 

설치 후 인덱스 스캔으로 변경된 것을 확인할 수 있습니다.
testdb=# explain analyze select * from test_table where test_column like '%TEXT%';
                                                      QUERY PLAN                                                       
-----------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test_table  (cost=22.42..1245.43 rows=313 width=298) (actual time=0.021..0.029 rows=6 loops=1)
   Recheck Cond: ((test_column)::text ~~ '%TEXT%'::text)
   ->  Bitmap Index Scan on trgm_idx  (cost=0.00..22.35 rows=313 width=0) (actual time=0.014..0.014 rows=6 loops=1)
         Index Cond: ((test_column)::text ~~ '%TEXT%'::text)
 Total runtime: 0.051 ms
(5 rows)
단, 3글자 미만에 대한 패턴검색 시 table full scan의 비용범위를 초과할정도로 인덱스 스캔비용이 급격히 증가하여 옵티마이져가 table seq scan을 강제하므로 글자수에 대한 제약사항 대처는 application레벨로 넘겨야 할 듯합니다.

prepare statements 와 casting

POSTGRESQL 2015. 4. 21. 16:32
상수값으로 잘 실행되는 SQL 구문이 parepare 구문을 이용하면 오류가 발생하는 경우가 있습니다. 이는 바인드변수로 SQL을 실행할때 묵시적형변환이 지원되지 않기 때문입니다.

 

상수값으로 실행한 결과입니다.
test=# create table test_table(col1 numeric);
CREATE TABLE
test=# insert into test_table values(1);
INSERT 0 1
test=# explain select col1 from test_table where col1 = '1';
                                  QUERY PLAN                                   
-------------------------------------------------------------------------
 Seq Scan on test_table  (cost=10000000000.00..10000000026.38 rows=7 width=32)
   Filter: (col1 = 1::numeric)
(2 rows)

 

prepare 구문으로 실행한 결과입니다.
test=# prepare foo(varchar) as
test-# select col1 from test_table where col1 = $1;
ERROR:  operator does not exist: numeric = character varying
LINE 2: select col1 from test_table where col1 = $1;
                                               ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
test=#

 

prepare 구문상 형변환을 명시하여 실행한 결과입니다.
test=# prepare foo(varchar) as
select col1 from test_table where col1 = $1::numeric;
PREPARE
test=# execute foo('1');
 col1 
------
    1
(1 row)