2011년 11월 20일 일요일

[JAVA] 스트링 배열선언

중괄호는 스트링 배열 선언 시 선언문에서만 사용할 수 있다.
예를들어

  • (잘못된 예)
String[] s;
s = {"aaa","aab","aac"};
  • (옳은 사용방법)
int[] arr new int[]{1,2,3};

2011년 11월 19일 토요일

[android] SimpleCursorAdapter 사용하기

SimpleCursorAdapter

SimpleCursorAdapter는 커서를 XML 파일에 정의된 TextViews 혹은 ImageViews로 컬럼을 맵핑시키는 쉬운 어댑터이다. 당신은 어떤 컬럼을 원하는지 어떤 뷰에 컬럼을 보여주고 싶은지 명시할 수 있다. 그리고 이러한 뷰의 모습을 정의하는 XML파일은 두가지 형태로 바인딩된다. 첫째로 만약 SimpleCursorAdapter.ViewBinder가 가능하다면, setViewValue(android.view.View, android.database.Cursor, int)가 호출된다. 만약 리턴값이 참이면 바인딩이 실행된다. 만약 리턴값이 거짓이고 바인딩 되는 뷰는 TextView 라면 setViewText(TextView, String)가 호출된다. 만약 리턴 값이 거짓이고 바인딩되는 뷰가 ImageView라면 setViewImage(ImageView, String)이 호출된다. 만약 적절한 바인딩이 발견되지 않으면 IllegalStateException이 던져진다. 만약 이 어댑터가 필터링과 함께 사용되면 예를들어 AutoCompleteTextView와 같은 당신은 SimpleCursorAdapter.CursorToStringConverter와 FilterQueryProvider 인터페이스가 필터링프로세스를 컨트롤한다. 자세한 내용은 convertToString(adnroid.database.Cursor) 그리고 runQueryOnBackgroundThread(CharSequence)에 대해서 내용을 참조할 수 있다.

(원문)

An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file. You can specify which columns you want, which views you want to display the columns, and the XML file that defines the appearance of these views. Binding occurs in two phases. First, if a SimpleCursorAdapter.ViewBinder is available, setViewValue(android.view.View, android.database.Cursor, int) is invoked. If the returned value is true, binding has occured. If the returned value is false and the view to bind is a TextView, setViewText(TextView, String) is invoked. If the returned value is false and the view to bind is an ImageView,setViewImage(ImageView, String) is invoked. If no appropriate binding can be found, an IllegalStateException is thrown. If this adapter is used with filtering, for instance in an AutoCompleteTextView, you can use the SimpleCursorAdapter.CursorToStringConverter and the FilterQueryProviderinterfaces to get control over the filtering process. You can refer to convertToString(android.database.Cursor) andrunQueryOnBackgroundThread(CharSequence) for more information.

2011년 11월 3일 목요일

[JAVA] ResultSet의 결과수에 따라 로직을 만들려고 할때...

자바에서 ResultSet으로 결과를 Fetch 한 뒤 총 몇개의 열이 Fetch 되었나는 다소 복잡하다.

conn = DBHandler.getConnection()

pstmt = conn.prepareStatement(Query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = pstmt.executeQuery();

rs.last();
int vFetchedRow = rs.getRow();
rs.beforeFirst();

이후 다시
while(rs.next){
/// codes
}

해도 에러가 나지 않는다.

[JAVA] ResultSet의 getFetchSize(int)에 대해

getFetchSize(int)는 총 몇개의 결과가 리턴되었는지를 나타내는 것이 아니라
1회당 fetch 되는 건수를 나타낸다.
API를 보면
setFetchSize를 이용해서 이 숫자를 변경 할 수도 있다.

만약 ResultSet에 총 몇개의 데이터가 리턴되었는지를 보려면
rs.last()
int row_cnt = rs.getRow();
하면된다.

2011년 11월 2일 수요일

[Oracle] 튜닝보고서

* 문제점
> 사용자가 많지 않은데 오라클+톰캣이 느린경우. 특별한 쿼리나 스크립트가 돌지 않은 상황이다.

* 힌트
> i/o 사용량을 확인하는 쿼리로 확인 결과 엄청난(?) 양의 쿼리가 필요없이 DB에서 돌고 있다.
> 쿼리
select xx.*

from
(select
a.ACTION action_a
,a.ACTION_HASH action_hash_a
,a.ADDRESS
,a.BUFFER_GETS
,a.CHILD_LATCH
,a.COMMAND_TYPE
,a.CPU_TIME
,a.DISK_READS
,a.ELAPSED_TIME
,a.EXECUTIONS
,a.FETCHES
,a.FIRST_LOAD_TIME
,a.HASH_VALUE
,a.INVALIDATIONS
,a.IS_OBSOLETE
,a.KEPT_VERSIONS
,a.LOADED_VERSIONS
,a.LOADS
,a.MODULE MODULE_a
,a.MODULE_HASH MODULE_HASH_a
,a.OPEN_VERSIONS
,a.OPTIMIZER_MODE
,a.PARSE_CALLS
,a.PARSING_SCHEMA_ID
,a.PARSING_USER_ID
,a.PERSISTENT_MEM
,a.ROWS_PROCESSED
,a.RUNTIME_MEM
,a.SERIALIZABLE_ABORTS
,a.SHARABLE_MEM
,a.SORTS
,a.SQL_TEXT
,a.USERS_EXECUTING
,a.USERS_OPENING
,a.VERSION_COUNT
,b.ACTION
,b.ACTION_HASH
,b.AUDSID
,b.CLIENT_IDENTIFIER
,b.CLIENT_INFO
,b.COMMAND
,b.CURRENT_QUEUE_DURATION
,b.FAILED_OVER
,b.FAILOVER_METHOD
,b.FAILOVER_TYPE
,b.FIXED_TABLE_SEQUENCE
,b.LAST_CALL_ET
,b.LOCKWAIT
,b.LOGON_TIME
,b.MACHINE
,b.MODULE
,b.MODULE_HASH
,b.OSUSER
,b.OWNERID
,b.PADDR
,b.PDDL_STATUS
,b.PDML_ENABLED
,b.PDML_STATUS
,b.PQ_STATUS
,b.PREV_HASH_VALUE
,b.PREV_SQL_ADDR
,b.PROCESS
,b.PROGRAM
,b.RESOURCE_CONSUMER_GROUP
,b.ROW_WAIT_BLOCK#
,b.ROW_WAIT_FILE#
,b.ROW_WAIT_OBJ#
,b.ROW_WAIT_ROW#
,b.SADDR
,b.SCHEMA#
,b.SCHEMANAME
,b.SERIAL#
,b.SERVER
,b.SID
,b.SQL_ADDRESS
,b.SQL_HASH_VALUE
,b.STATUS
,b.TADDR
,b.TERMINAL
,b.TYPE
,b.USER#
,b.USERNAME
from v$sqlarea A,
v$session B
where A.disk_reads > 10000
and A.ADDRESS = B.SQL_ADDRESS(+)
AND A.HASH_VALUE = B. SQL_HASH_VALUE(+)
order by A.disk_reads desc) xx
where rownum < 30

* 해결방법
> 모든 jsp 에서 참조하고 있는 의미없는 쿼리를 로그인 시 1회 로드하여 세션에 저장하도록 변경

* 현재 값과 튜닝 후 예상 값(결과)
>

2011년 11월 1일 화요일

[Oracle] 오라클 메모리(1)

SGA - System Global Area
* share pool, database buffer cache, redo log buffer, java pool, large pool 이 있는 시스템 영역

PGA - program global area
* 한 프로세스 혹은 쓰레드를 위해 개별적으로 할당되는 공간
* pga 확인 쿼리 - select * from v$process

UGA - user global area
* 전용서버모드 dedicated server 에서만 존재하며 shared server 모드에서는 PGA = UGA 이다.

[Oracle] DB 모니터링 쿼리

  • 쿼리가 optimize 가 제대로 되지 않아서 SQL cache 안에서 쉽게 사라지지 않는 쿼리를 확인 하는 쿼리 (1)

SELECT Disk_Reads DiskReads, Executions, SQL_Text SQLText
FROM
(
SELECT Disk_Reads, Executions, LTRIM(SQL_Text) SQL_Text,
Operation, Options,
Row_Number() OVER
(Partition By sql_text ORDER BY Disk_Reads * Executions DESC)
KeepHighSQL
FROM
(
SELECT Avg(Disk_Reads) OVER (Partition By sql_text) Disk_Reads,
Max(Executions) OVER (Partition By sql_text) Executions,
sql_text, p.operation,p.options
FROM v$sql t, v$sql_plan p
WHERE t.hash_value=p.hash_value AND p.operation='TABLE ACCESS'
AND p.options='FULL' AND p.object_owner NOT IN ('SYS','SYSTEM')
AND t.Executions > 1
)
ORDER BY DISK_READS * EXECUTIONS DESC
)
WHERE KeepHighSQL = 1
AND rownum <=30;
  • 쿼리가 optimize 가 제대로 되지 않아서 SQL cache 안에서 쉽게 사라지지 않는 쿼리를 확인 하는 쿼리 (2)
SELECT * FROM
(SELECT
sql_text,
child_number,
disk_reads,
executions,
first_load_time,
last_load_time
FROM v$sql
ORDER BY elapsed_time DESC)
WHERE ROWNUM < 10;

  • 특정 DISK_READS 횟수 이상만큼의 쿼리를 보는 쿼리 - 문제가 되었던 getsesseioninfo.jsp 는 141484750 회 읽혔음 OTL

SELECT parsing_user_id, executions, sorts, command_type, disk_reads,
sql_text
FROM v$sqlarea
WHERE disk_reads > &&access_level
ORDER BY disk_reads desc;
  • V$SQL_WORKAREA_ACTIVE, V$SQL_WORKAREA, V$SQL 뷰를 이용하여 현재 시스템에서 할당된 실행 영역 중 top 10을 찾습니다.
SELECT c.sql_text, w.operation_type, top_ten.wasize
FROM ( SELECT *
FROM ( SELECT workarea_address, actual_mem_used wasize
FROM v$sql_workarea_active
ORDER BY actual_mem_used desc)
WHERE ROWNUM <= 10 ) top_ten,
v$sql_workarea w, v$sql c
WHERE w.workarea_address = top_ten.workarea_address
AND c.address = w.address
AND c.child_number = w.child_number
AND c.hash_value = w.hash_value;

  • V$SQL_WORKAREA 뷰를 통해서 다음과 같이 SQL 실행 메모리를 가장 많이 필요로 하는
    top 10 실행 영역을 구할 수 있다.
SELECT *
FROM ( SELECT workarea_address, operation_type, policy, estimated_optimal_size
FROM v$sql_workarea
ORDER BY estimated_optimal_size DESC )
WHERE ROWNUM <= 10;
  • 커서가 열린 뒤 닫히지 않아서 메모리가 반환되지 못하는 경우
  • current cursor 가 몇백 몇천개인지 확인할 것
SELECT ss.username username, se.sid SID_NUM , p.spid SPID_NUM,
sum(decode(name,'recursive calls',value)) "Recursive Calls",
sum(decode(name,'opened cursors cumulative',value)) "Opened Cursors",
sum(decode(name,'opened cursors current',value)) "Current Cursors"
FROM v$session ss, v$sesstat se, v$statname sn, v$process p
WHERE se.statistic# = sn.statistic#
AND ( name like '%opened cursors current%'
OR name like '%recursive calls%'
OR name like '%opened cursors cumulative%')
AND se.sid = ss.sid
and ss.paddr=p.addr
AND ss.username is not null
GROUP BY ss.username , se.sid , p.spid
order by "Current Cursors" asc

  • 같은 쿼리지만 쉐어할 수 없어서 다른 쿼리로 인식되는 경우 카운트
select sql_text from v$sqlarea where version_count > 1;
  • PGA/UGA 사용량을 산출하는 쿼리

ttitle '**********< Program Global Area >**********'
ttitle '1. Current pga, uga session memory'

select a.sid, a.username, substr(a.program, 1, 25) as pgm, a.terminal,
max(decode(c.name, 'session pga memory', trunc(value/1000)||'K', 0)) pga,
max(decode(c.name, 'session uga memory', trunc(value/1000)||'K', 0)) uga
from v$session a, v$sesstat b, v$statname c
where a.sid = b.sid
and b.statistic# = c.statistic#
and c.name like 'session%'
group by a.sid, a.username, substr(a.program, 1, 25), a.terminal;

ttitle '2. Sum of current pga, uga session memory'

select 'Current PGA, UGA session memory SUM:' as sum,
sum(decode(c.name, 'session pga memory', trunc(value/1000),0))||'K' pga_sum,
sum(decode(c.name, 'session uga memory', trunc(value/1000),0))||'K' uga_sum
from v$session a, v$sesstat b, v$statname c
where a.sid = b.sid
and b.statistic# = c.statistic#
and c.name like 'session%';

ttitle '3. Max(peak) pga, pga session memory'

select a.sid, a.username, substr(a.program, 1, 25) as pgm, a.terminal,
max(decode(c.name, 'session pga memory max', trunc(value/1000)||'K', 0)) pga_max,
max(decode(c.name, 'session uga memory max', trunc(value/1000)||'K', 0)) uga_max
from v$session a, v$sesstat b, v$statname c
where a.sid = b.sid
and b.statistic# = c.statistic#
and c.name like 'session%'
group by a.sid, a.username, substr(a.program, 1, 25), a.terminal;

ttitle '4. Sum of max(peak) pga, uga session memory'

select 'Max(peak) PGA, UGA session memory SUM:' as sum,
sum(decode(c.name, 'session pga memory max', trunc(value/1000), 0))||'K' pga_m_sum,
sum(decode(c.name, 'session uga memory max', trunc(value/1000), 0))||'K' uga_m_sum
from v$session a, v$sesstat b, v$statname c
where a.sid = b.sid
and b.statistic# = c.statistic#
and c.name like 'session%';



  • i/o 사용량이 많은 순서대로 프로세스를 확인하는 쿼리
select A.disk_reads, A.sql_text,
B.sid, B.serial#
from v$sqlarea A,
v$session B
where A.disk_reads > 10000
and A.ADDRESS = B.SQL_ADDRESS(+)
AND A.HASH_VALUE = B. SQL_HASH_VALUE(+)
order by A.disk_reads desc;

  • 메모리 사용량이 많은 순서대로 프로세스 확인(자세한 확인이 필요함...)
Select
D.sid "SID",
D.username "Oracle User",
D.program "Program",
D.module "Module",
D.status "Status",
D.type "Type",
D.server "Connection",
to_char(D.logon_time,'YYYY-MM-DD HH24:MI:SS') LOGON_TIME,
D.osuser OS_USER ,
decode(D.lockwait,null,'','Blocking') LLOCK,
decode(D.taddr,null,'','TX') TRAN,
A.User_Name,
D.machine MACHINE,
B.Disk_Reads,
B.Buffer_Gets,
B.Rows_Processed,
C.SQL_Text,
A.Address
From V$Open_Cursor A,
V$SQLArea B,
V$SQLText C,
sys.v_$session D
Where 1=1
AND B.ADDRESS = D.SQL_ADDRESS
AND B.HASH_VALUE = D.SQL_HASH_VALUE
And A.Address = C.Address
;

  • UGA/PGA 확인 쿼리
  • 사용량이 peak 일때 돌려보자

SELECT
s.sid sid
, lpad(s.username,12) oracle_username
, lpad(s.osuser,9) os_username
, s.program session_program
, lpad(s.machine,8) session_machine
, (select ss.value from v$sesstat ss, v$statname sn
where ss.sid = s.sid and
sn.statistic# = ss.statistic# and
sn.name = 'session pga memory') session_pga_memory
, (select ss.value from v$sesstat ss, v$statname sn
where ss.sid = s.sid and
sn.statistic# = ss.statistic# and
sn.name = 'session pga memory max') session_pga_memory_max
, (select ss.value from v$sesstat ss, v$statname sn
where ss.sid = s.sid and
sn.statistic# = ss.statistic# and
sn.name = 'session uga memory') session_uga_memory
, (select ss.value from v$sesstat ss, v$statname sn
where ss.sid = s.sid and
sn.statistic# = ss.statistic# and
sn.name = 'session uga memory max') session_uga_memory_max
FROM
v$session s
ORDER BY session_pga_memory DESC