oracle.java.com 가면 OSX용 JDK 1.6버젼대를 찾을 수 없는데,

JDK6은 아래 apple 사이트에서 받을 수 있네요.

https://developer.apple.com/downloads/index.action


그리고 dmg 패키지로 jdk를 설치하면


/Library/Java/JavaVirtualMachines


아래 경로에 설치가 됩니다.


데이터 일괄 삭제 작업과 관련해 transaction을 이용해 처리하는 stored procedure가 있었다.
로직을 좀 변경한 뒤에 테스트를 하려고 하는데, 다 지워버리면 다시 테스트하기가 어려워 transaction을 걸고 테스트 후 rollback할 생각으로 테스트를 했는데...

예상과는 다르게 trasaction이 rollback이 되지 않는 것이었다. --;;
원인은 drop table!!

fk가 걸린 테이블이 있어 지우고자 하는 원본 데이터를 임시테이블에 담아 지우는 로직이 있는데, 거기서 기존 임시테이블 남아있으면 안되서, drop table을 하고 있었는데 이 drop table문의 경우에는 transaction이 시작되면 기존 transaction을 commit하고 수행해버린 것이다.

그래서 메뉴얼을 찾아봤는데...
Note

DROP TABLE automatically commits the current active transaction, unless you use the TEMPORARY keyword.


이렇게 잘 나와있었다.

그런데 마지막 부분에... unless use the TEMPORARY keyword!!

테이블을 만들 땐 CREATE TEMPORARY로 잘 만들고는 drop할때는 drop table을 한것이다.

상황에따라 다르겠지만, 임시테이블의 경우에는 transaction처리가 문제없이 된다는 점을 잘 알아둬야겠다.


TEMPORARY table의 경우에는 drop문도 transaction 처리가 가능하다!

ORDER BY 구문을 이용할 때 아래와 같이 order 방식을 다르게 SELECT를 할 필요가 있는 경우가 있다.

SELECT *
FROM tablename
ORDER BY A DESC, B ASC, C ASC

위와 같이 쿼리를 날리게되면, index를 만들 때 A,B,C 컬럼에 composit index가 생성이 되어 있더라도, 정렬이 모두 DESC나 ASC로 되어 있다면 결국 index를 제대로 활용 못하고 filesort가 나게 된다.

도움말을 찾아보면 아래와 같이 INDEX 생성 시점에 columnname [ASC | DESC] 와 같이 정렬 순서를 컬럼별로 줄 수 있다고 써있다.




CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name 
[index_type] 
ON tbl_name (index_col_name,...) 
[index_option ...] 

index_col_name: 
col_name [(length)] [ASC | DESC] 

index_type: 
USING {BTREE | HASH | RTREE} 

index_option: 
KEY_BLOCK_SIZE value | index_type | WITH PARSER parser_name



그래서 실제로 적용해 봤는데, 그래도 계속 filesort가 발생해서 도움말을 좀 더 읽어봤더니... 역시나 --;;

An index_col_name specification can end with ASC or DESC. These keywords are allowed for future extensions for specifying ascending or descending index value storage. Currently, they are parsed but ignored; index values are always stored in ascending order.

앞으로 추가될 기능이라는 얘기가 있었다. parse는 잘 되지만 무시한다고 --;;

google reader에서 소식을 접하고 homepage에 가 봤는데, 오늘 공개되었군요.
거의 6개월만의 새 버젼이군요~

어떤 기능들이 추가되었는지, 어떤 버그들이 수정되었는지 살펴볼까 했는데... 내용이 넘 많네요.
버젼이 올라간 정도를 봐서도 대략 짐작이 되지요~

3.0버젼업을 앞둔 API 하위 호환성 얘기부터, runtime 변경, api 변경, 새 기능, bugfix... 많군요.
그 중 중요 내용을 정리한 Lucene News에 나온 내용들 중에서도 개인적으로 관심을 갖게된 부분은 

Near real-time search capabilities added to IndexWriter

너무 늦었으니, 오전에 좀 더 꼼꼼히 보고 추가할까 합니다.
그럼 이만

음.. 제목이 낚시성이긴 한데... 하도 가끔 설치를 하다보니 한번 설치하면 담에 설치할 때 까먹고 해서.. 정리할 겸 적어본다.

다른 건 다 상관없는데, mysql사이트의 install 방법을 보다보면, mysql설치시 다음과 같이 db를 초기화 하는 부분이 있다.
shell> scripts/mysql_install_db --user=mysql

이렇게 초기화를 하게되면, 내가 원하는 위치에 설치되지 않고 mysql이 정한 기본 경로를 따르게 된다.
또한 mysql 프로세스를 띄우는 방식 역시 메뉴얼에 나온데로 아래와 같이

bin/mysqld_safe  --user=mysql &

띄울 경우, 처음 설치한 사람은 그렇다쳐도 다른 사람이 해당 서버에서 process만 확인해서는 my.cnf가 어디에 있는지, 혹시 여러개의 my.cnf가 존재하는 경우 어떤 my.cnf를 사용해 서버가 시작되었는지 헷갈리는 문제가 있다.

File Name Purpose
/etc/my.cnf Global options
SYSCONFDIR/my.cnf Global options
$MYSQL_HOME/my.cnf Server-specific options
defaults-extra-file The file specified with --defaults-extra-file=path, if any
~/.my.cnf User-specific options

위 순서는 unix 기준이고, windows는 
File Name Purpose
WINDIR\my.iniWINDIR\my.cnf Global options
C:\my.iniC:\my.cnf Global options
INSTALLDIR\my.iniINSTALLDIR\my.cnf Global options
defaults-extra-file The file specified with --defaults-extra-file=path, if any

그래서 아래와 같은 방법으로 설치를 하고 프로세스를 띄우는 것이 좋은것 같다.
일단 my.cnf를 먼저 준비(my.cnf파일 내부 옵션들에 대한 설명)를 하고, 해당 설정파일 내부에 설치를 원하는 위치 등의 정보를 먼저 수정한 후,초기화 script시 parameter로 해당 my.cnf의 위치를 전달해 주고
shell> scripts/mysql_install_db --defaults-file=/etc/my.cnf --user=mysql

mysql 프로세스를 띄울 때도, 아래와 같이 parameter로 my.cnf 파일의 위치를 전달해 주면,
bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

설치자 외에도 해당 서버에서 process만 mysql을 grep해 보면, my.cnf 위치가 명시되어 있어 보다 쉽게 파악이 가능하다는 점이 있다.

보다 자세한 설치 방법은 이글을 참고하면 좋을 것 같다.
mysql index관련 검색을 하다 재미있는 내용의 글을 발견 정리하려고 올립니다.
mysql의 경우에도 버젼업이 많이 되고 있어, 최신 버젼의 optimizer에 대해서 아는바가 없지만, 현재 4.x대를 사용 중이라 optimizer의 문제를 너무 많이 느끼고 있어서 공감했던 글입니다.


위 글의 내용을 정리하면 대략 다음과 같습니다.

CREATE TABLE t (
  id INT UNSIGNED AUTO_INCREMENT,
  type INT UNSIGNED,
  level TINYINT unsigned,
  ...
  PRIMARY KEY(id),
  KEY `type` (type)
) ENGINE=InnoDB;

위와 같은 테이블이 있고, 해당 테이블에 대해 아래와 같은 쿼리를 사용하려고 합니다.

SELECT id FROM data
WHERE type=12345 AND level > 3
ORDER BY id

정확한 이해를 위해 보다 자세한 내용을 소개하자면

  • t라는 테이블에는 약 10,000,000개의 row가 있다.
  • 'type'이라는 index의 선택도는 대략 하나의 value에 대해 평균 100row정도 (예를 들어 type 'x'를 검색하면 결과가 평균 100개정도 나온다는 의미)
  • 쿼리 수행 시간이 오래 걸린다.
  • EXPLAIN 결과에서 보면 key는 primary key를 이용한다고 하고 rows는 10,000,000, extra 정보에는 using where라고 나온다.
  • 'type' index를 이용한 EXPLAIN 결과에서는 rows는 110rows, extra정보에는 "using where;using filesort"라고 나온다.

실제 실행 시간은 mysql이 제시한 방법 보다는 'type' index를 이용한 쿼리가 나은 결과를 보이는데, 그럼 쿼리를 어떻게 고치면 'type' index를 사용할 수 있게 할 수 있는지에 대해 7가지 방법에 대해 소개를 하고 있습니다.

몰랐던 방법들도 있네요.
내용이 어렵진 않으니 원문을 참고하세요~

'programming > MySQL' 카테고리의 다른 글

mysql을 잘 설치하고 잘 띄우기  (0) 2009.06.01
MySQL unique index생성 시 size 제한  (0) 2009.02.17
mysql의 'ON DUPLICATE KEY UPDATE' 구문  (4) 2007.08.27
mysql 5.1에서 innodb인 테이블에 데이터 타입은 varchar에 collation은 latin1으로 size가 1000 정도인 컬럼에 unique index를 걸려고 했는데 다음과 같은 에러가 났다.

Specified key was too long; max key length is 767 bytes

그냥 index의 경우도 걸어보면 다 걸린것 같지만 내부적으로는 부분 index만 걸린다는 사실.
unique index의 경우에는 부분적으로 unique를 걸 수 없으므로 아예 에러가 난다.

레퍼런스를 찾아보면... db engine별로 지원하는 unique index의 크기가 틀렸다.
또 collation이 latin1인지 utf8인지에 따라 다르다 latin1인 경우 1글자가 1byte이지만, utf8인 경우 한글자가 3byte이므로 1000을 3으로 나누면 size 333까지만 지원하게 된다.
다음과 같은 내용을 mysql online document에서 확인할 수 있다.

Prefix lengths are storage engine-dependent (for example, a prefix can be up to 1000 bytes long for MyISAM tables, 767 bytes for InnoDB tables). Note that prefix limits are measured in bytes, whereas the prefix length inCREATE INDEX statements is interpreted as number of characters for non-binary data types (CHARVARCHAR,TEXT). Take this into account when specifying a prefix length for a column that uses a multi-byte character set. For example, utf8 columns require up to three index bytes per character.

참고로 InnoDB의 index page size는 16Kb이다. (컬럼의 길이가 너무 길면 index 자체도 별 효과가 없을 수 있으니 제한을 두는건 맞는 것 같은데. 767이라는 제한은 어디서 온걸까 싶어서.. 대충 256*3하면 768인데...)

p.s. 구글에서 'mysql column 767' 이라고 검색하면 제일 상단에 MySQL Bugs...라고 나오길레 버그인가 했더니 초기 5.0버젼에서 768-1024 length인 primary key가 만들어진다는 버그에 대한 리포팅이었다.
쩝... 계속 발전하는 루씬의 모습을 보면 기분은 좋긴한데...
2.0으로 만들었던 걸 2.3으로 다시 만들어서 런칭한 날 2.4가 나오다니 --;;

게다가 2.4에는 바뀐것도 많다.
심지어 changelog 형식도 바뀌었군요 ㅋㅋ


역시나 별로 관심 없지만 뭐가 바뀌었는지 궁금하긴 한 사람들을 위해 중요 point만 정리해볼까 합니다.

가장 큰 변화
Lucene 2.4.0 includes index format changes that are not readable by older versions of Lucene. Lucene 2.4.0 can both read and update older Lucene indexes. Adding to an index with an older format will cause it to be converted to the newer format.
index format을 또(과거 2.1.0에서 한번 변경 되었다.) 변경하셨다. 그래서 이전 버젼으로 만든 lucene서버에서는 새 index format을 읽을 수 없다. 당연하지만 새 버젼으로 만든 lucene으로는 기존 버젼의 index를 읽을 수 있지만... 

기타 변화들 중 중요한 변화를 change log에서 뽑아볼까 했으나 이미 여기에 정리가 다 되어 있는 것 같아서 그냥 한글로만 정리해 볼까 합니다.

- "InstantiatedIndex"라는 class가 생겼는데, 기존의 RAMDirectory보다 훨씬 빠르다고 한다. 테스트 해 봐야겠네요.

- IndexWrite가 indexing 중에 OS의 문제나 갑자가 power가 꺼져도 index가 깨지지 않는다고 한다. 이건 맘에 들지만.. 여지껏 index가 깨지는 걸 경험하질 못해서... --;;

LUCENE-997 : 검색 시 시간 제약을 둘 수 있게 되었다. 특정 시간이 넘어가지 않도록... 해당 시간이 넘어가면 "TimeExceeded Exception"를 발생시킨다고 한다. 이걸 외부에서 wrapping해서 처리한다고 삽질했던 기억이....

- NIOFSDirectory : to allow multiple threads to read from the same open file without locking. 이걸 쓰면 퍼포먼스가 좀 향상될라나??

- "now the filter is applied to a document before scoring is done" : 예전엔 filter로 거르기 전에 scoring을 다 했었나보네요 --;; filter 쿼리가 많이 빨라지지 않았을까요? 아이고 궁금해라...

- "IndexReader can be opened with new readOnly=true mode" : IndexReader를 readOnly모드로 열면 multithread환경에서 보다 나은 성능을 기대할 수 있다는데... 그럼 IndexSearcher를 그냥 만들면 알아서 readonly 모드로 열릴라나... 이것도 테스트 해봐야겠네요~
소스 받아서 확인해 봤는데... IndexSearcher를 생성하면 내부적으로 알아서 IndexerReader를 readonly로 생성하는군요. 
public IndexSearcher(String path) throws CorruptIndexException, IOException {
        this(IndexReader.open(path), true);
}


위에 나열한 변화 외의 변화들도... 평소의 변화들에 비해는 조금 큰 변화이니 처음 접하는 분들이야 그냥 쓰면 되겠지만 예전부터 사용하는 분들은 꼼꼼히 살펴보는 게 좋을 것 같네요~

그럼.. 게으른 포스팅 여기서 마물...

'programming > Java' 카테고리의 다른 글

lucene 2.9.0 available!! 루씬 새버젼 출시~  (0) 2009.09.29
lucene의 Release 2.2.0 2007-06-19 을 보다가...  (0) 2008.04.10
lucene 2.1.0 released  (1) 2007.02.21
현재 lucene 2.0.0을 쓰고 있는데, 2008년 2월 22일에 나온 2.3.1 버젼을 적용할 필요가 있는지를 살펴보다가, 예전에 블로깅한 lucene내부의 query를 escape하는 함수에 버그가 고쳐진 것을 발견했다.

이상하게도 &와 |에 대해서 escape이 빠져있다 생각했는데.. 버그였다니 --;;

17. LUCENE-881: QueryParser.escape() now also escapes the characters
'|' and '&' which are part of the queryparser syntax. (Michael Busch)

lucene의 버젼 별 변경 내역

'programming > Java' 카테고리의 다른 글

루씬 upgrade 되다!! (Lucene Java 2.4.0 available)  (4) 2008.10.31
lucene 2.1.0 released  (1) 2007.02.21
Java에서 XML관련 예외  (2) 2007.01.30
mysql을 사용하면서 처음 알게된 구문인데... INSERT 구문에 같이 쓰이게 된다.

명령어만 봐도 직관적으로 이해할 수 있는데...

INSERT할 때 KEY가 duplicate가 되었을 때, UPDATE하는 방법에 대해 정의할 수 있다.

예를 들어,
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
컬럼 a가 key라고 가정할 경우, 이미 컬럼 a의 값이 1인 row가 있을 경우 해당 row의 c컬럼의 값을 1 증가시키라는 의미이다.

프로그래머 입장에서는 귀찮게 select한 후 없으면 insert 있으면 update하는 것을 한방에 해결해 주긴 하지만, ANSI SQL이 아니라 그점이 좀 맘에 걸린다.

오늘 하고자 하는 얘기는... 쉽게 이해하는것 처럼 단순히 key에 대해서만 동작하지는 않는 다는 것이다.

메뉴얼을 잘 읽어본 분은 아시겠지만...

아래와 같은 경우에 동작하게 된다.
1. key
2. unique index

1번은 알고 있었는데, 2번을 모르고 있어서 만들어진 코드가 이해가 안가 살펴보다가 결국 메뉴얼을 정독하고 알게되었다. ^^

저 처럼 실수하는 분 없기를...
오늘 lucene 홈페이지 들어갔다가 알게됐다. 2월 14일에 새 release가 발표됐다.

lucene으로 프로그래밍 한 지 좀 지나서 또 가물가물 해졌지만... 그래도 관심이 있어 좀 읽어 봤는데, 몇 가지 내용만 정리해 봤다.

Changes
* 's'와 't'가 StopAnalyzer(StandardAnalyzer에서도 사용됨)의 stopword에서 제거됨.
* StandardAnalyzer의 CJK에 대한 unicode code point ranges가 update됐다.(CJ와 K로 분리됨)
* WildcardQuery의 queryString에 ? 나 *가 포함되어 있지 않으면 알아서 TermQuery를 수행한다. 이전 버젼의 경우에는 StringIndexOutOfBoundsException이 발생했었다
* deprecated되었던 doc.fields() 와 Enumeration을 제거
* write lock 파일이 Index directory에 생성됨. 이전에는 "org.apache.lucene.lockDir" or "java.io.tmpdir"였음.
 - 첨엔 write lock이 어디 있는지 몰라 헤맸었는데, 찾기 쉬워진 듯

New Feature
* ThaiAnalyzer와 ThaiWordFilter가 추가됨
 - 태국어쪽 작업하는 사람은 별로 없겠지만... 요즘 게임업체는 태국에 많이 진출했으니, 그 업체들에서 CS 툴의 검색 기능을 lucene으로 붙일 수 있을 듯 ^^''
* NGramTokenizer와 EdgeNGramTokenizer class 추가됐고, unit test를 통과
 - cjk analyzer는 특정 unicode 범위에 대해서는 2-gram 방식인걸로 알고 있는데, NGram을 응용하면 보다 나은 검색 시스템을 만들 수 있을까???
* IndexWriter에 document를 update(내부적으로는 delete then add)할 수 있는 method추가
 - 귀찮게 delete했다가 add할 것 없이 바로 update할 수 있으니 조금 편할 듯

더 자세한 내용은 아래에서...

출처 : http://svn.apache.org/repos/asf/lucene/java/tags/lucene_2_1_0/CHANGES.txt

rlike (REGEXP 의 synonyms임)
: like와 유사한데 뒤에 오는 표기법이 정규식임

관련 도움말 : http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html

<example>
SELECT *
FROM CLIP
WHERE daumname rlike '^고[[:alnum:]]?미' LIMIT 10;

정규식 사용을 해 보신분은 아시겠지만... 표기법이 희한하죠?
다른 언어에서 사용하는 방법과 좀 다릅니다. 보다 자세한 표기법은 아래에서 참고하시면 될 듯
http://dev.mysql.com/doc/refman/5.0/en/regexp.html

주의!
프로그래밍하긴 편할지 몰라도 성능은 좋지 못하다는 것.
mysql optimizer는 정규식 기반의 쿼리를 최적화하지 못합니다.

XML관련 처리 로직에서 아래와 같은 에러가 났다.

java.lang.NoSuchMethodError: org.w3c.dom.Element.getTextContent()Ljava/lang/String;
    keron.client.xmlutil.SimpleDomBuilder.w3cElemenetToSimpleElement(SimpleDomBuilder.java:43)
    keron.client.xmlutil.SimpleDomBuilder.createSimpleDocument(SimpleDomBuilder.java:32)
    keron.client.xmlutil.SimpleDomBuilder.createSimpleDocument(SimpleDomBuilder.java:19)

대략 sun에서 정의해 놓은 interface를 구현한 외부 구현체를 이용해서 사용하는데, 같은 소스를 독립 app로 돌리면 문제가 없는데, tomcat위에서 돌리면 위와 같은 에러가 난다.
그렇다고 모든 tomcat위에서 예외가 발생하는 것은 아니다.

아마도 그 위에 돌아가는 web app와 관련된 어떤 문제려니... 추측만 무성하다. 회사 동료와 같이 살펴봤는데, 정확한 원인을 못 찾았다.

결국 구글신의 도움으로
http://www.velocityreviews.com/forums/t144510-problems-with-jboss-an-xerces.html
위 사이트에서 다음과 같은 도움을 받았다.

element.getTextContent() // 이 부분 대신

Text contents = (Text) element.getFirstChild();
result.setValue(contents.getNodeValue());

이렇게 변경해서 해결했다. 시간이 없어 정확히 찾아보진 않았지만, 혹시 같은 문제로 고생하는 분 도움이 되시길..

아는 사람은 다 알겠지만...

특정 컬럼에 index를 걸어 둔 경우,
'x%'는 index를 이용할 수 있지만, '%x' 또는 '%x%'는 index를 이용할 수 없다.

조금만 생각해 보면 알겠지만, index는 문자의 왼쪽을 기준으로 인덱스를 만들어 두었기 때문이다.
그런데 만약 반드시 '%x'를 구현해야 한다면 어떻게 해야 할까??
요즘 읽는 책에 간단한 방법이 나왔길래 적어본다.

컬럼 하나를 추가해서 문자열을 뒤집어 저정한 후 index를 걸어두는 것이다.

쩝.. 알고보면 간단한데, 이런 생각은 해 본적이 없다.

사람이름을 예로들어...

col1
이하늘
김하늘
이기택
...

에서 '하늘'이라는 이름을 언능 찾고 싶으면, 아래와 같이 이름을 뒤집어 놓은 컬럼을 추가하고

col1        col2
이하늘       늘하기
김하늘       늘하김
이기택       택기이
...


col2에도 index를 걸고,

SELECT * FROM user WHERE col2 like '늘하%'

라고하면 간단히 해결~


사실 이 얘기를 쓰려고 한 것은 아니었는데...

mysql쪽 책을 보다가 mysql에는 rlike라는 구문이 있음을 알게 됐다.
이건 다시 정리해서~~

'programming > MySQL' 카테고리의 다른 글

mysql의 rlike (REGEXP)  (0) 2007.02.01
MySQL utf-8 글자 깨짐 해결  (0) 2006.09.26
mysql에서 stored procedure 만들면서 주의 할 것  (2) 2006.09.22
일반적으로 많이 사용하는 list control, datagrid control등등의 control에 어떤 데이터 값을 동적으로 채워주고자 할 때, 알아야 하는 것이 data provider이다.

보다 구체적인 data provider의 사용법에 대해 알고 싶다면,
About data provider and collections
Using Data Providers
을 참고하면 된다.

일단은 내가 직접 해 본, list control, datagrid control에 대해 간략히 정리해 보면...
동적으로 두 control들에 넣을 데이터를 담을 data class를 정의한다.

1. DataGrid control
public class Bookmark {       
   public var tags:String;
   public var description:String;
   public var time:String;       

   public function Bookmark (pTags:String, pDesc:String, pTime:String)
   {
       tags = pTags;
       description = pDesc;
       time = pTime;
   }
}
이렇게 Bookmark라는 class를 정의하고,

var b1:Bookmark = new Bookmark("tag1, tag2", "bookmark1", "2006-01-01");
var b2:Bookmark = new Bookmark("tag3, tag1", "bookmark2", "2006-01-11");
var tagArray:Array = new Array();
tagArray.push(b1);
tagArray.push(b2);

grid1.dataProvider = tagArray;

이렇게 해 주면 된다. 그런데 여기서 실제 datagrid에는 세개의 컬럼이 있는데 어떤 컬럼에 어떤 데이터를 보여주는지는 datagrid를 넣은 XML에서 설정할 수 있다.

<mx:DataGrid x="10" y="10" width="472" id="grid1">
   <mx:columns>
       <mx:DataGridColumn headerText="" dataField="col1"/>
       <mx:DataGridColumn headerText="Description" dataField="description"/>
       <mx:DataGridColumn headerText="Tags" dataField="tags"/>
       <mx:DataGridColumn headerText="Time" dataField="time"/>
   </mx:columns>
</mx:DataGrid>

2. List Control
list control의 경우 객체 배열을 data provider로 지정했을 경우, 화면 출력에 사용하는 컬럼의 설정은 default로는 label이라는 이름을 먼저 찾고, 별도로 지정하고자 할 경우에는 아래와 같이 labelField를 지정하면 된다.

<mx:List x="10" y="10" height="212" id="listTag1" width="260" labelField="tags"></mx:List>

일단 여기까지 정리...

'programming > flex2.0' 카테고리의 다른 글

Flex 2 mxml에 actionScript 정의하는 방법  (0) 2006.11.08

MXML에 ActionScript를 정의하는 방법은 두 가지가 있다.

1. MXML안에 직접 정의하는 방법
in test.mxml
<mx:Script>
  <![CDATA[
       import mx.controls.Alert;

       function sayHello(){
           Alert.show("hi")
       }
  ]]>
</mx:Script>

2. 외부 파일에 정의하고 그 파일을 지정하는 방법
in test.mxml
<mx:Script source="as3/test.as">
</mx:Script>


in as3/test.as (
import mx.controls.Alert;

function sayHello(){
  Alert.show("hi")
}

2번처럼 mx:Script를 정의할 때 source를 넣어준 경우 inline에 actionscript를 넣을 수 없다.


'programming > flex2.0' 카테고리의 다른 글

Flex 2에서 control들의 data provider 설정 방법  (2) 2006.11.16
SQL Server 2000까지는 없던 내용이라 SQL Server 사용자는 생소할 만한 object에 대해 간단히 소개해 볼까 합니다.

SYNONYM : 동의어, 유의어

아직 제대로 번역된 글을 보지 못해 한글로는 어떻게 표현해야 할지 궁금하지만... 유사객체(?)ㅋㅋ (인포믹스에서는 동의어라고 하나보네요. - 출처)
뜻만으로 미뤄 짐작해보면 alias(별칭)과 유사한 그런 개념입니다.
엔진 차원에서 이렇게 만들어진 object를 어떻게 관리하는지를 정확히는 모르는 관계로 deep한 내용은 건너뛰고...

일단 MSDN 문서에서 CREATE SYNONYM에 대한 도움말 링크는 여기

문법은 간략히 설명하자면
CREATE SYNONYM name FOR objectName
object에 올 수 있는 것은 도움말을 참조하시고... 대략 stored procedure류, view, table 등이 올 수 있습니다.

유의할 점은... 생성시 대상이 되는 object가 존재하지 않아도 된답니다. 실행 시 object의 여부를 check한다고 하네요.

SYNONYM은 local, remote object 모두에 만들 수 있습니다.

그럼 이런 넘은 어디에 쓰라고 만들었을까?? 함 고민해 봤는데..
처음엔 원격 DB table에 check constraint(관계설정)을 걸 수 있을 줄 알았는데, 여기를 보니 그건 안된다고 나와있네요 --;; 해보진 않아서 아는 사람한테 해 보라고 부탁만 해 놨지만..



그럼 도대체 어디에 쓸까???
함 생각해봤는데...

이미 구축된 database를 물리적으로 여러대로 분산할 때, program source를 전혀 고치지 않고 분리가 가능할거 같더라구요. 분리된 database object에 대해 실제 program에 사용되는 database object name과 동일한 synonym만 만들어 주면 되니까요.

또 뭐가 있을까???
생각나는게 없네요 --;; 오라클에는 원래 있었던 기능이라니 혹시 또 다른 좋은 쓰임새를 아시는 분은 덧글 부탁드립니다.  

(추가) Synonym의 쓰임새
SQL Server 2005 adds the capability to create synonyms for database objects, which simplifies the readability of the queries that use objects outside of their own schema (that is, objects with multipart names). Synonyms can also be used to create a level of abstraction over their base objects, thus enabling the easy switching of base objects without affecting the code that references them.
(출처 : http://www.informit.com/articles/article.asp?p=364263&seqNum=3&rl=1)

1. 가독성을 높혀준다.
2. 쉽게 실제 object를 교체 가능하므로 해당 object를 참조하는 코드에 영향을 주지 않는다.
라는 이점이 있다네요.


(추가2) 글 쓰고나니 계속 더 찾아지는 article들...
이 기사에서는 'Synonyms as an Abstraction Layer'라고 표현하는데.. 아주 적절한 표현인 것 같네요.
갑자기 예전에 써 놓은 글이 생각나서 찾아보다 여기에 다시 옮기게 됐네요.

예전에 써 놓은 글 입니다.

실제 글 주소는 트랙백으로 걸기로 하고...

다시 살펴보다보니 SQL Server 2005로 넘어오면서 병행 제어 방법이 변경되었네요. ^^''
이름은 그럴싸하게 만들었던데, 왠지 oracle쪽과 약간 유사해진 느낌이...
원문 주소는 여기
역시 원문 사라질 걸 대비해서 파일로 남깁니다.




간단하게 위 문서에 아래와 같은 부분이 있는데..

Historical Behavior

Historically, the concurrency control model in SQL Server at the server level has been pessimistic and based on locking. While locking is still the best concurrency control choice for most applications, it can introduce significant blocking problems for a small set of applications.

The biggest problem arises when locking causes the writer-block-reader or reader-block-writer problem. If a transaction changes a row, it holds exclusive locks on the changed data. The default behavior in SQL Server is that no other transactions can read the row until the writer commits. Alternatively, SQL Server supports ‘read uncommitted isolation’, which can be requested by the application either by setting the isolation level for the connection or by specifying the NOLOCK table hint. This nonlocking scan should always be carefully considered prior to use, because it is not guaranteed to return transactional consistent results.


간단히 정리해 보면...
"SQL Server는 병행제어 모델로 비관적 알고리즘인 locking을 사용해 왔다. locking은 아직까지 대부분의 application에서 병행제어 방법으로는 가장 좋은 방법이긴 하지만 작은 규모의 application에서 중요한 blocking 문제를 야기시킬 수 있다.
가장 큰 문제점은 locking이 writer-block-reader 혹은 reader-block-writer의 원인이 되는 것이다. 기본적으로 SQL Server에서는 writer가 commit하기 전까지 어떤 트랜잭션도 row를 읽을 수 없다. 대신 application에서 isolotion level을 지정하거나 NOLOCK 테이블 힌트를 이용해 요청할 수 있는 'read uncommitted isolation'을 지원한다. 일관성 있는 결과를 보장하지 않으므로 이런 방법으로 locking하지 않은 채 사용하는 것은 주의해야 한다."

대략 정리했는데, 큰 틀은 맞겠지만 소소하게 틀린 부분은 많을테니 잘못된 부분 지적해 주시면 감사하고 이해하고 보시거나 ㅋㅋ
나머지는 시간날 때 날 잡고...

그리고 Oracle 최신 버전에는 혹시 다른 변화가 있는지도 같이 한번...

Oracle 10i의 메뉴얼 중 Concurrency Control 관련 부분 메뉴얼은 여기
파일은

실제 이런 문제를 겪는 경우도 그리 흔치 않고, 아주 가끔 발생한다면 알아 채기도 힘들다.
그래서 그런지 해결책에 대한 논의를 많이 보지도 못했다.

추후 reference 용도로 링크를 하나 달고, 페이지가 삭제될 위험(?)에 대비해 내용을 파일로 저장해 둔다.


관련 글
- A Collection of JVM Options


--------------------------------------------------------------




'programming > Java' 카테고리의 다른 글

Java에서 XML관련 예외  (2) 2007.01.30
Lucene 검색 시 and Query와 Filter의 차이점  (2) 2006.09.29
lucene의 Highlighter를 한글에 적용...  (2) 2006.09.12

Lucene 검색을 할 때,

특정 조건을 AND로 추가해서 Query할 수도 있고,
특정 조건을 Filter로 추가해서 Query할 수도 있다.

총 검색되는 갯수는 같지만, 간단하지만 보이지 않는 차이를 정리해 보면...
* AND로 검색을 하면 score에 해당 내용이 반영이 되어 정확도로 정렬할 경우 해당 내용이 반영된다.
* AND로 검색을 하면 별로도 추가로 검색을 하는 것이므로, 부하가 있는 쿼리의 경우는 AND조건 검색보다 Filter로 걸러내는 것이 속도가 빠르다. (검색된 것들 중에서 filtering을 하는 것이니 당연히 빠르겠죠? 전체 인덱스의 크기가 크면 클 수록 and query를 이용한 것 보다 훨씬 빠를테니까요.)

조금 더 자세히 몇 가지를 설명하자면...
Lucene in Action과 현재 licene 2.0 버젼이 filter 부분이 차이가 좀 있는데
DateFilter라는건 없어졌다.

그리고 내 경우는 기존에 사용하던 Filter도 있어서...
추가로 한가지 Filter를 추가한 case라서..

ChainedFilter에 두가지 filter를 추가해서 생성해서 사용했다.
참고 : http://lucene.apache.org/java/docs/api/index.html

Lucene에서는 numeric 범위 연산을 제공하지 않아, 숫자에 대해 범위 연산을 할 경우, 사용하는 자리수 많은 부족한 부분에 0을 채워줘야 한다.

간단하게 예를 들어 0~999까지의 숫자를 range검색하려면... 인덱싱할 때
1 -> 001
42 -> 042
999 -> 999

이렇게 인덱싱을 하고 검색할 때도 "032 TO 311" 이렇게 검색해 줘야만 제대로 검색이 가능하다.
그러므로 속도가 많이 느리다.

아래 출처에 보면, 음수를 포함하는 범위 검색을 하는 방법도 나와 있으니 필요한 분은 참고 하시길...

출처 : http://wiki.apache.org/jakarta-lucene/SearchNumericalFields

출처의 내용은 첨부 파일로 올려 놓는다.


SearchNumericalFields - Jakarta-lucene Wiki.mht



mysql을 사이트에 나온데로만 설치하고 아무 변경 없이 실행 후...

database와 table을 utf8로 만들고, stored procedure를 만들어 java에서 call하는데 한글이 깨지는 현상이 있었다.

db url에도 characterEncoding도 넣어보고, property에 charset을 utf-8로도 해 보고 하다가...
이것 저것 해 봐도 안됐었는데...

어디선가 보고 /etc밑에 my.cnf 파일이 없어서 mysql안에 있는 것 복사해서 넣고, 아래 내용을 추가해서 mysql을 재시작 하고나서 해결

[client]
character-set=utf8

[mysqld]
init_connect=SET collation_connection = utf8_general_ci
init_connect=SET NAMES utf8
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci

이 넘의 한글 문제... 머리아프다.. 어디 제대로 정리 된 곳 없을까?
주로 MS-SQL에서 작업을 하다, mysql에서 처음으로 stored procedure(이하 sp)를 만들면서, 5분이면 될 것을 수십분은 걸린 것 같다 --;;
에러가 정확한 위치를 알려주질 않는다.

아래의 정리한 내용은 MS-SQL에 익숙하고 mysql을 사용해 보지 않은 분이 보면 무자게 도움이 될 것 같다.

- IF문을 쓸 때 END IF문이 있어야 하며, END IF문 뒤에는 ;를 붙여야 한다.
   ex> IF (test IS NULL) THEN
            SELSET 'ok';
         END IF;

- auto increment값을 얻어올 때는 LAST_INSERT_ID()을 이용한다.
   ex> SET serverId = LAST_INSERT_ID();

- CREATE PROCEDURE문 전에 delimeter문을 이용해 delimeter를 ';'가 아닌 다른 걸로 변경하고 뒤에 다시 변경할 것
   ex> delimiter //                  # delimeter를 //로 변경
         CREATE PROCEDURE xxx
                  .....
                  .....
         END;
         //                                # 실제 한 command가 종료됨을 의미

         delimeter ;                     # 다시 ;로 변경



일단 여기까지

'programming > MySQL' 카테고리의 다른 글

MySQL utf-8 글자 깨짐 해결  (0) 2006.09.26
java, mysql stored procedure 호출  (0) 2006.09.22
DBDesigner 4와 MySQL 4.1의 연결  (2) 2006.01.25
mysql에 stored procedure 만들기
delimiter //        

CREATE PROCEDURE getServerId(ip VARCHAR(15), OUT serverId tinyint)
BEGIN
SELECT id INTO serverId FROM tServer WHERE serverIp = ip;
END;
//

delimiter ;

- mysql에서는 ;가 command의 종료를 의미하는데 stored procedure의 경우 여러 query의 조합이라 중간에 ;가 들어갈 수 있는데, 그러면 문법 오류로 간주되므로 delimiter를 임시로 다른 걸로 바꾼 후 sp를 만들고 다시 예전 delimiter로 변경하는 것임.


java에서 call하는 코드
try {
   String CLASS_NAME = "com.mysql.jdbc.Driver";
   String DB_URL = "jdbc:mysql://localhost:3306/test";
   String USR = "id";
   String PASSWD = "pw";
  
   Class.forName(CLASS_NAME);
   Connection con = DriverManager.getConnection(DB_URL, USR, PASSWD);
             
   CallableStatement stat = conn.prepareCall("call getServerId(?, ?)");
   stat.setString(1, "127.0.0.1");
   stat.registerOutParameter(2, Types.TINYINT);
   stat.execute();
          
   System.out.println(stat.getByte(2));
} catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
} catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
}

'programming > MySQL' 카테고리의 다른 글

mysql에서 stored procedure 만들면서 주의 할 것  (2) 2006.09.22
DBDesigner 4와 MySQL 4.1의 연결  (2) 2006.01.25
DECLARE @var1 int  (5) 2006.01.20
검색 결과에서 검색어를 highlight 시키는 기능을 구현하는데, lucene의 sandbox의 Highlighter를 이용해 봤다.


샘플 소스와 동일하게하고 analyzer만 CJKAnalyzer로 변경했는데... 결과는

"학교에서 우리 선생님께서 나에게 좋은 대학교를 골라 주셨다."에서 "학교"를 검색했다고 가정하면

변환한 결과는 아래와 같이 나온다.
"<B>학교에서</B> 우리 선생님께서 나에게 좋은 <B>대학교를</B> 골라 주셨다"

검색한 단어만이 아닌 조사까지 포함해서 처리가 된다.
혹시 단어만 하일라이팅 시키는 방법을 알고 계신분 있으신가요???


lucene을 이용해 검색을 구현할 때, 검색어에 lucene에서 사용하는 특수기호를 넣으면, 잘못 반영 될 소지가 있어, lucene에서 사용하는 특수 기호들에 대해서는 escape(기호 앞에 \를 추가)을 해 줘야 한다.

정규식을 이용해 간단하게 구현했는데, Lucene in Action 책을 보니 sandbox에 있는 js를 참고하라고 해서 홈페이지에 가 보니 없었다.

결국 알고보니 api에 추가가 되었다.
QueryParse.escape();

나 처럼 뻘짓하는 분 없기를...  

but....

http://lucene.apache.org/java/docs/queryparsersyntax.html
여기 가 보면 lucene에서 사용하는 특수기호들에 대한 설명이 나와 있다.
'+ - && || ! ( ) { } [ ] ^ " ~ * ? : \'

그런데 lucene의 escape 코드를 보면 '&&'와 '||'은 빠져 있다.
(2007년 6월 19일 발표된 2.2.0버젼에서 bugfix 되었습니다.)

직관적으로 이해 하겠지만 search value에  &&는 and로 ||는 or로 변환되어 처리되므로,
실제  &&나 ||를 검색해야 하는 경우 코드를 따다 수정해서 사용해야 할 듯.



실제 lucene 코드

url이 해당 사이트의 서비스를 매우 직관적으로 나타낸다.

QuickRef.org

현재 아래의 언어들에 대한 reference를 제공한다.
C, C++, CSS, HTML, HTML DOM, Java, JavaScript, MySQL, Perl, PHP, and Ruby
더 좋은 점은 실제 doc문서를 바로 보여준다. ajax를 이용해 해당 사이트의 내용을 바로 보여주는 듯...
프로그래밍 할 때 이용할 수 있는 자동 완성 기능이 구현되어 정확히 모르고 찾을 때도 매우 유용할 듯.

오늘 알게 됐으니, 낼 부터 함 써봐야겠다 ^^
 
MS SQL만 하다가 MySQL, Oracle을 조금은 알아야만 할 입장이 되어 버렸네요...
이것 저것 비교해 보면 재미있던데, 기본적으로 datatype 부터...
알아 가면서 하나씩 정리해 보면 재미있을 것 같네요.


Oracle 10g Release 2
http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#i54330

SQL Server 2005
http://msdn2.microsoft.com/en-us/library/ms187594.aspx

MySQL
http://dev.mysql.com/doc/refman/5.1/en/data-types.html



드디어 Dell의 새 모니터와 새 시스템을 받아 기분 좋게 시스템 세팅 중에...
새로 3.2를 설치하고 테스트 하는데 ant build시 제목 표시줄과 같은 에러가 발생

원인은 eclipse 내에 ANT_HOME path가 잘못 걸려 있어서 발생했던 것.

'Window->Preferences->Ant->Runtime' 여기서 ANT_HOME 버튼 눌러 맞는 위치로 설정해 주면 해결~

참고 : http://www.herrodius.com/blog/?p=42

'programming > Java' 카테고리의 다른 글

[갱신]lucene의 검색 값 escape  (0) 2006.09.11
java Date 관련 Quick reference  (0) 2006.07.27
Hibernate Quick Reference  (0) 2006.07.27

* 오늘 날짜 구하기
- new Date();
- Calendar now = Calendar.getInstance();
  now.getTime();

* 어제 날짜 구하기
  Calendar now = Calendar.getInstance();
  now.add(Calendar.DAY_OF_MONTH, -1);
  now.getTime();

* 날짜 포맷을 원하는 형태로 바꾸기
       Calendar now = Calendar.getInstance();
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      sdf.format(now.getTime());    // 결과는 String

* 지 맘데로의 날짜를 담은 문자열을 다른 형태로 convert

        String dateStr = "200707211541122";
        SimpleDateFormat oldFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       
        try {
            System.out.println(newFormat.format(oldFormat.parse(dateStr)));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

* yyyy-MMM-dd 형태 parse 시 주의 할 점
      String regDt = "27/Jul/2006:00:00:00";
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MMM/dd:hh:mm:ss",
               Locale.US);

       try {
           System.out.println(sdf.parse(regDt).toString());
       } catch (ParseException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }

-> 위와 같이 Locale을 지정하지 않으면 한글 OS에서는 parse 오류가 난다.

* 특정날짜가 무슨 요일인지 알아보기
       String regDt1 = "2006-11-14";
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);

       Calendar cal = Calendar.getInstance();

       try {
           cal.setTime(sdf.parse(regDt1));
           System.out.println(cal.get(Calendar.DAY_OF_WEEK));
       } catch (ParseException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }

주의: cal.DAY_OF_WEEK라고 하면 처음 생성했던 instance의 값을 리턴한다.

 * 날짜 간의 비교
   
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Calendar now = Calendar.getInstance();
        now.add(Calendar.HOUR, -3);
        Date before3hour = now.getTime();
       
        try {
            if (before3hour.before(sdf.parse(regdttm))) {
                return true;
            } else {
                return false;
            }
        } catch (ParseException e) {
            return false;
        }
Hibernate 사용하기

1. 객체를 이용하여 저장하는 방법
           Transaction tx = session.beginTransaction();
           Cafe cafe = new Cafe();
           cafe = new Cafe();
           cafe.setId(Id);
           cafe.setName(name);
           session.save(cafe);
           tx.commit();


2. key 값을 이용해 값이 존재하는지 확인한 후 저장하는 방법
       Session session = HibernateUtil.getCurrentSession();

       Cafe existCafe = (Cafe) session.get(Cafe.class, grpId);
       
       if (existCafe == null) {
           Transaction tx = session.beginTransaction();
           Cafe cafe = new Cafe();
           cafe = new Cafe();
           cafe.setId(id);
           cafe.setName(name);
           session.save(cafe);
           tx.commit();
           System.out.println("inserted");
       }
       else{
           System.out.println("already exist");
       }

       HibernateUtil.closeSession();

3. key가 아닌 값을 이용해 존재하는지 확인한 후 저장하는 방법
* createQuery 안의 문장은 SQL Query가 아니라 Hibernate에서 사용하는 HQL(Hibernate Query Language) 이다.
  * 자세한 문법은 http://www.hibernate.org/hib_docs/v3/reference/ko/html/queryhql.html

       Session session = HibernateUtil.getCurrentSession();

       Keyword k = (Keyword) session.createQuery(
               "select k from Keyword as k where keyword = ?").setString(0,
               keyword).uniqueResult();
       if (k == null) {
           Transaction tx = session.beginTransaction();
           Keyword kw = new Keyword();
           kw.setKeyword(keyword);
          
           session.save(kw);
           tx.commit();
           System.out.println("inserted");
       } else {
           System.out.println("already exist");
       }

       HibernateUtil.closeSession();

4. 자동 증가값 받기
* 걍 강제 casting
   int id = (Integer) session.save(kw);

5. DB의 identity 컬럼 관련 XML 설정
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.daum.cafe.search.weblog.entity">
   <class name="Keyword" table="tKeyword">
       <id name="id" column="id">
           <generator class="identity" />
       </id>
       <property name="keyword" type="string" column="keyword" />
   </class>
</hibernate-mapping>

6. 복합키 관련 XML 설정
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.daum.cafe.search.weblog.entity">
   <class name="DTBC" table="tableD">
       <composite-id>
           <key-property name="Id" type="int" column="Id" />
           <key-property name="keywordId" type="int" column="keywordId" />
       </composite-id>
       <property name="count" type="int" column="count" />
   </class>
</hibernate-mapping>
* 참고 : 복합키를 구현하려면 Serializable을 반드시 implements해 주어야 한다. 그렇지 않으면 'composite-id class must implement Serializable' 예외가 발생한다.

+ Recent posts