Console API 쪽으로 넘어 오고 나서 조금 낮설었던 단어 중에 하나가 UPSERT였다.


OAS의 경우는 데이터를 Delete할 경우에 데이터 자체를 없애는 반면 Console의 경우는 deleted field를 '1'로 Setting하여 데이터 자체를 남겨 두었다. 그리고 같은 이름의 데이터가 들어 오게 될 경우 기존 데이터의  deleted field를 '0'로 Flip하여서 재 사용 하는 방식인 것이다.


기본적인 Idea는 괜찮았는데, 문제는 어떻게 구현되어 있는지 모른다는 것이었다.

암만해도 Console API자체가 Framework화 되어 있고, 

Model Configuration하면 자동으로 API가 생성되니 내부적으로 그냥 구현하나 보다 하고 생각하고 있었다.


근데 최근에 API에 데이터를 입력하는데 오류가 발생한다는 Issue를 Follow up하다 보니 API Framework내부에서 MariaDB의 INSERT ON DUPLICATE KEY UPDATE 구문을 사용하는 걸 발견하였다.


https://mariadb.com/kb/en/mariadb/insert-on-duplicate-key-update/


INSERT INTO ...

ON DUPLICATE KEY UPDATE

  col=expr ....


DUPLICATE CHECK 대상은 Unique Index가 생성된 Field에 대해서다. 따라서 PK도 포함된다는.

괜찮은 기능인데 Oracle에서는 보았던 기억이 없다.


뭐.. Oracle이 이런 세세한 부분에서 조금 기능이 부족한 부분이 있으니깐 뭐..


참고로 Console API에서 발생했던 이슈는..

Facebook Mapping관련 테이블인데 

다른 테이블과 달리 Facebook Account ID를 PK로 두고 , brand, member를 Unique로 두고 있는데  

( 보통 Console은 Incremental Id를 PK로 사용하는데 대체 누가 이런 테이블 구조를 만들었는지..)

PI팀에서 기존 매핑을 지우고 새로운 Account Id를 brand, member 에 Mapping하고 싶었는데 

(brand, member) 의 Unique index때문에 새로운 row를 생성하지 않고 기존 데이터의 deleted column을 0으로 Filp하는 방식으로 처리되서 문제가 발생한 것이었다.

( API Framework내부에서 PK관련 FIELD들을 ON DUPLICATE KEY UPDATE clause에서 빼버리기 때문인데 뭐  reasonable하긴 한데 이런 부분에서 좀 문제가 생길 수 밖에 없었다. )

Facebook의 AdNetwork사업을 11월에 접기로 했으니 

Code수정 없이 그냥 DBA에게 해당 PK를 업데이터 하는 Query를 실행하도록 하여 이슈를 해결하도록 했다.

'개발자세상 > Database관련' 카테고리의 다른 글

Open Cursor issue  (0) 2014.10.25
listagg function and ORA-01489  (0) 2014.01.09
Oracle TEMP 파일 삭제  (0) 2013.09.23
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Overlap 데이터 구하기  (0) 2013.08.04
Posted by headiron
,

이번에 Production system에서 NullPointerException으로 API call이 failed 되는 이슈가 발생했다.
Review 하던 중에 Maximum Open Cursor도 함께 발생해서, 느낌은 Maximum Open Cursor 때문에 NullPointerException도 발생한 것 같은데 들어주는 사람이 없네.. -.-

어쨋든, 이슈는 이슈고, DBA 얘기로는 Cursor 개수 Count는 Session 단위라고 하니, 해당 이슈가 다시 발생할 개연성은 많이 줄은 듯 하다. ( 특히나 얼마전에 Upgrade 작업으로 DB Session들이 한 번 Restart 됐으니. )

그래도 일단은 Cursor Monitoring은 해야 할 듯 해서 Article을 찾아 보니 아래 Article이 괜찮아 보인다.

http://www.orafaq.com/node/758


현재 OPen Cursor 개수를 확인하는 Query

select a.value, s.username, s.sid, s.serial#
from v$sesstat a, v$statname b, v$session s
where a.statistic# = b.statistic#  and s.sid=a.sid
and b.name = 'opened cursors current';


현재 최대 Open Cursor 개수와 Maximum Cursor Limitation Check

select max(a.value) as highest_open_cur, p.value as max_open_cur
from v$sesstat a, v$statname b, v$parameter p
where a.statistic# = b.statistic# 
and b.name = 'opened cursors current'
and p.name= 'open_cursors'
group by p.value;


Posted by headiron
,

근간에 Project를 진행하면서 Multi Row로 저장된 데이터를 한 Field로 처리할 방법을 Search하다 알게된 listagg 함수,
GROUP BY 와 함께 사용하면 같은 Key Field 값을 가진 ROW 데이터를 합칠 수 있다.

SELECT KEYFIELD, listagg( field_name, ',') within group (order by field_name)
FROM table
GROUP BY KEYFIELD

워낙 이런 Case가 많아서, 자주 사용하기 시작했는데,
오늘 listagg 함수를 사용한 Query에서 ORA-01489 에러가 발생..

찾아 보니... Oracle에서 문자열 Concatenate를 4000 byte 까지 밖에 지원하지 않는 것이다.
크.. 언제적 제약사항이 아직도 발목을 잡는 건지..

Googling을 해 보았더니.. StackOverflow에 관련 내용도 있고,
여러 내용을 리뷰해 보니, Query Level에서 이 문제를 해결할 방법은 아래와 같이 XML TYPE으로 변경해서 Aggregation 하는 방법 밖에는 없다.
http://stackoverflow.com/questions/14864055/listagg-function-and-ora-01489-result-of-string-concatenation-is-too-long

select tm.product_id, 
       rtrim(extract(xmlagg(xmlelement(e, tm.book_id || '(' || tm.score || '),')), 
               '/E/text()').getclobval(), ',')
  from tl_product_match tm
 where tm.book_id is not null 
 group by tm.product_id;

문제는.. XML로 변환 하고, Aggregation 한후 정규식으로 XML TAG를 제거 하고, 이를 다시 CLOB으로 변경하니, Performance가 엄청 좋지 않다는 점..

지금 Project는 Java Program 단에서 해결해 낼 수 있을 것 같긴 한데..
Oracle도 예전 코드들 때문에 이런 제약사항에 시달리는 걸 보면..
너무 앞장서서 나가는 것도 생각 만큼 좋지는 않은 듯...

'개발자세상 > Database관련' 카테고리의 다른 글

UPSERT ? INSERT ON DUPLICATE KEY UPDATE  (0) 2016.09.24
Open Cursor issue  (0) 2014.10.25
Oracle TEMP 파일 삭제  (0) 2013.09.23
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Overlap 데이터 구하기  (0) 2013.08.04
Posted by headiron
,

DB Migration 중에 TEMP 파일을 많이 사용하는 쿼리를 돌리게 되서 TEMP 파일을 늘려 놨더니 , 이젠 서버 공간이 부족해서 파일들을 삭제 해야 할 일이 생겼다.

DB 내렸다 올려야 하나 생각하고 좀 귀찮았는데..
TEMP 파일은 생각 보다 손 쉽게 삭제 할 수 있었다.

SQL> ALTER DATABASE TEMPFILE '/oradata/temp02.dbf' DROP INCLUDING DATAFILES;


출처는 아래 페이지에서..

http://www.orafaq.com/node/2

'개발자세상 > Database관련' 카테고리의 다른 글

Open Cursor issue  (0) 2014.10.25
listagg function and ORA-01489  (0) 2014.01.09
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Overlap 데이터 구하기  (0) 2013.08.04
Stored Procedure 개발 / 실행  (0) 2012.12.08
Posted by headiron
,
SELECT SEGMENT_TYPE, SEGMENT_NAME, TABLESPACE_NAME, TRUNC((SUM(BYTES)/1024)/1024,2) as "용량(MB)"
FROM DBA_SEGMENTS   
WHERE SEGMENT_TYPE IN ('TABLE', 'INDEX', 'TABLE PARTITION', 'TABLE SUBPARTITION')
AND OWNER = '사용자명'
GROUP BY SEGMENT_TYPE , SEGMENT_NAME, TABLESPACE_NAME
ORDER BY 1 desc, "용량(MB)" desc;
출처 : http://koreantramp.tistory.com/216

기존에 개발해 놓았던 LOG 분석 시스템에서
동시 요청 정보를 확인해 보고 싶어서 작업을 돌려 봤더니 세월아 .. 내월아...
체크해 보니.. 시간이 Overlap 되는 정보를 확인하려면 시간 정보에 index가 있어야 하는데.. Index가 없어서 실행 계획이 엉망인것이다.

그래서 Index를 생성해 보았더니.. 이 Index가 생성되는데.. 세월아 .. 내월아..
다행이 예전에 back ground로 query 돌리던 script가 있어서 실행해 보았더니,
한참 돌다가.. TEMP 테이블스페이스가 용량이 부족해서 에러 발생...
https://forums.oracle.com/thread/369703
결국 TEMP 테이블 스페이스 용량을 추가 한 후 정상 생성..
그런데.. Index 생성하는데.. 하루 이상 걸렸다...

뭐.. 그래도 Index 생성했더니... 전에 보다는 몇 백배는 빨라 졌다.
근데.. 동시 요청 정보를 Account Level로 Check했더니 특정 User의 동시 사용 정보 때문에 다른 sequential 요청도 동시 요청으로 잡히는 문제 점 확인...

결국 코드를 수정했더니.. 전엔 Index access로만 데이터를 처리할 수 있었던 Query가
테이블 access가 발생하면서 다시 느려지는...

결국 User 정보를 Index가 다시 추가하는데...
속도는 느리고.. 또 Index 생성하다가 용량 부족으로 에러 나고... -.-

주말내내 Index 생성되는 걸 기다려야 할 듯 하다..

근데 Index 테이블 생성하고.. 위 Query로 체크해 보니..
Index가 테이블 사이즈 보다 훨 커져 버렸다.

말로만 듯던.. ( 어찌보면 분석 시스템에서는 필연적인..) 인덱스가 테이블보다 더 커지는 현상...

예전에 여러 회사에서 시스템 운영하면서 한번도 격어 보지 못했던..
대용량 DB 시스템 관련 이슈를 개인용 ( 물론 업무적으로 개발한거지만.. ) 분석툴에서 겪게 될 쭐이야....

좀 중구 난방 으로 개발 운영하여서 누더기 갇기는 하지만..
그동안 겪어 보고 싶던 대용량 데이터를 다루는 기쁨이라고 나 할 까...


'개발자세상 > Database관련' 카테고리의 다른 글

listagg function and ORA-01489  (0) 2014.01.09
Oracle TEMP 파일 삭제  (0) 2013.09.23
Overlap 데이터 구하기  (0) 2013.08.04
Stored Procedure 개발 / 실행  (0) 2012.12.08
오라클 실행계획 보기  (0) 2010.03.03
Posted by headiron
,

그동안에 API에서 CONCURRENT 관련 이슈가 많이 생겨서 RATE CONTROL FEATURE를 개발했다.
개발하고 나니, 어떤 CLIENT가 얼마가 쓰고 있는 지를 현재 모르고 있다는..
그 전에 CLIENT 들 한테 INFORM을 해야 하는데...
다행히 LOG 분석툴에 DATA는 쌓여 있는데... 동시 사용하는 건지 체크를 어떻게 해야 하나 고민이 되었다.

일단 LOG 데이터를 하나씩 읽어서 시간대가 겹치는 LOG가 있는지를 확인한 후 LOG 가 있을 경우 동시 사용자 정보로 넣는 코드를 생각해 보았는데...
내가 생각해 보아도 너무 무식한 방법인 것이다.

MATT하고도 잠시 상의해 보고 했는데.. MATT도 딱히 생각나는 IDEA가 없는 듯 하다.

결국 GOOGLEING을 했더니.. 나랑 비슷한 이슈를 가졌던 사람들이 있고 QUERY로 해결 할 수 있는 방법이 떡하니 있는 것이 아닌가..

http://stackoverflow.com/questions/2037618/overlapping-time-in-sql-server

http://docs.oracle.com/cd/B28359_01/appdev.111/b28396/long_vt.htm#i1007490


내 경우는...  Index가 날짜 FIELD에 맞추어 생성이 안되어 있어서 값이 RETURN되지 않아서
INDEX 생성  시키면서 그냥 데이터 하나씩 읽어서 중복 데이터 CHECK하는 원래 생각대로 개발 하였다.

역시 세계는 넓고 개발자는 많다는 거...
그나저나 이렇게 인터넷 세상이 발달한 때에 개발자로 산다는 게 얼마다 다행인지..


'개발자세상 > Database관련' 카테고리의 다른 글

Oracle TEMP 파일 삭제  (0) 2013.09.23
오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Stored Procedure 개발 / 실행  (0) 2012.12.08
오라클 실행계획 보기  (0) 2010.03.03
ORACLE 사용자 생성  (0) 2010.03.03
Posted by headiron
,

Stored Procedure가 성능 면에서는 일반 Query 보다 앞선 다는 걸 알면서도 선뜻 사용하기가 주저해진다. 익숙하지 않는 부분이 하나 일 것이고, 디버깅도 쉽지 않기 때문일 것이다.

뭐... 요즘처럼 JDBC 이외에 ORM 까지 사용하는 세상에 Stored Procedure는 정말 찬밥 이기 쉬운 듯 하다.

하지만... 장점도 있는 것이... DB dependent 한 Code를 Stored Procedure로 숨길 수도 있는데.. 이 부분은 Product를 개발하는 입장에서는 정말 매력적인 장점이 아닐까 생각 된다.

뭐.. 어쩌다가 요즘 혼자 개발하다가 갑자기 Stored Procedure를 쓸 일이 생기니 좀 당황 스러웠다.

생각해 보면 예전에 DBA가 SQL*PLUS에서 Stored Procedure를 어떻게 실행하는 지 물어 보기도 했으니.. 그리 부끄러워 할 일은 아닌 듯 하다.

일단 Stored Procedure를 실행 할려면 아래 처럼 하면 된다.

var rc refcursor;

execute ( ... , : rc);

print rc;

우리회사는 보통 Cursor를 제일 마지막에 사용하다 보니 위에 처럼 Output Cursor를 마지막에 넣어 주고... print 문으로 Cursor를 찍어 본다.

그리고 개발을 하다 보니 Stored Procedure가 LOOPING을 도는 것 같은 데 확인할 방법이 없다.

뭐.. 이럴 때는 Query를 확인 해야 하는 데 아래와 같이 CURSOR OPEN 하기 전에 Query를 찍으면 도움이 될 듯 하다.

dbms_output.put_line(p_sql);

근데.. 이걸 했는데도 Query가 콘솔에 찍히지 않아 왜 그런가 확인해 봤더니 아래 환경 변수를 ON 시켜 주어야 한다나..

SET SERVEROUTPUT ON

확인해 보니깐..
조건절을 잘못 넣어서 2억개가 넘는 ROW를 CURSOR에 넣고 있었다...-.-


어쩟든 기존에 개발 되어 있던 여러 Stored Procedure를 참조해서 필요한 Stored Procedure를 개발했는데.
참 어처구니 없는 것이... PL/SQL에는 문자열 split 함수가 없다.
인터넷을 뒤지고 다녔더니.. 다들 자기 들 만의 문자열 split 함수를 올려 놨다.
마침 Vinayak이 방에 놀러 왔길 래 사정 얘기를 했더니..
OAS에서 Cursor, Pipe를 이용해 구현한 함수와 사용 예제를 보여주어 덕분에 쉽게 해결 됐다.
다음에 또 stored procedure를 개발할 일이 생겼을 떄는 split 함수가 지원 되기를 기원한다.


'개발자세상 > Database관련' 카테고리의 다른 글

오라클 DB에서 테이블마다 용량 구하기  (0) 2013.08.10
Overlap 데이터 구하기  (0) 2013.08.04
오라클 실행계획 보기  (0) 2010.03.03
ORACLE 사용자 생성  (0) 2010.03.03
ORA-30557  (0) 2009.12.09
Posted by headiron
,
1. explain plan for
   select * from emp;

    select * from table(dbms_xplan.display);

2. explain plan
    set statement_id = 'stmt1' for
    select * from emp;

    select * from table(dbms_xplan.display('plan_table','stmt1','all'));
    select * from table(dbms_xplan.display('plan_table','stmt1','typical'));
    select * from table(dbms_xplan.display('plan_table','stmt1','basic'));

'개발자세상 > Database관련' 카테고리의 다른 글

Overlap 데이터 구하기  (0) 2013.08.04
Stored Procedure 개발 / 실행  (0) 2012.12.08
ORACLE 사용자 생성  (0) 2010.03.03
ORA-30557  (0) 2009.12.09
Oracle Table Column Rename  (0) 2009.10.28
Posted by headiron
,
CREATE USER 사용자명
IDENTIFIED BY 패스워드
DEFAULT TABLESPACE 테이블스페이스명
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT
ACCOUNT UNLOCK;

GRANT DBA,RESOURCES TO 사용자명;

ALTER USER 사용자명 DEFAULT ROLE ALL;

GRANT UNLIMITED TABLESPACE TO 사용자명;

'개발자세상 > Database관련' 카테고리의 다른 글

Stored Procedure 개발 / 실행  (0) 2012.12.08
오라클 실행계획 보기  (0) 2010.03.03
ORA-30557  (0) 2009.12.09
Oracle Table Column Rename  (0) 2009.10.28
오라클 Function Compile/ 생성시 Ora-00942 오류..  (1) 2009.06.22
Posted by headiron
,
오라클에서 Field 사이즈를 조정하려고 했더니 

"ORA-30556: functional index is defined on the column to be modified"
메시지가 뜬다.

인터넷 뒤져 보니 functional index를 삭제한 후 조정하면 된다고 하는데

Enterprise Manager 나 다른 Tool에서 Functional index를 찾을 수 있는 방법이 없다.

결국 염대리님이
"select * from USER_IND_EXPRESSIONS;" 쿼리를 알려 주셔서 functional index를 찾을 수 있었고 해당 index를 drop 한 후 원래 나오던 column_expression대로 다시 생성을 하니 정상적으로 동작한다.


SQLPLUS>select * from USER_IND_EXPRESSIONS where table_name = '테이블명';

출력 결과 )
INDEX_NAME        TABLE_NAME     COLUMN_EXPRESSION       COLUMN_POSITION
XXXX                    YYYY                NLSSORT("ID",'nls_sort=''BINARY_CI''')    1

SQLPLUS>drop index XXXX;

SQLPLUS>ALTER TABLE XXXX MODIFY ( CCCC VARCHAR2(256));

SQLPLUS> create index XXXX on YYYY(NLSSORT("ID",'nls_sort=''BINARY_CI'''));


참조 : USER_IND_EXPRESSIONS Functional index expressions in user's indexes and indexes on user's tables



'개발자세상 > Database관련' 카테고리의 다른 글

오라클 실행계획 보기  (0) 2010.03.03
ORACLE 사용자 생성  (0) 2010.03.03
Oracle Table Column Rename  (0) 2009.10.28
오라클 Function Compile/ 생성시 Ora-00942 오류..  (1) 2009.06.22
impdp / expdp  (0) 2009.06.19
Posted by headiron
,