2014년 12월 31일 수요일

디아블로3 드디어 시즌종료! (2015년 2월 3일 예정)

디아블로3 드디어 시즌종료! (2015년 2월 3일 예정)

출처: http://kr.battle.net/d3/ko/blog/17152343?utm_content=external-sso&utm_medium=other&utm_source=App



시즌 종료: 무엇이 바뀌나요?
시즌 종료: 무엇이 바뀌나요?
네팔렘이여, 때가 다가오고 있습니다. 그 동안 새로운 영웅이 오고 가며 정벌 임무가 완수되었고, 대균열은 정화되었으며 순위표는 영웅들의 이름으로 가득 채워졌습니다.
첫 번째 시즌이 마감되어감에 따라, 이제 어떤 일들이 있어날지 궁금해하시는 분도 많으실 텐데요. 이 블로그를 통해 시즌 1 종료가 여러분께 어떤 영향을 주는 지와 시즌 2를 준비하는 분들을 위해 예상되는 변화를 알려드리고자 합니다.
목차:

시즌 전환

시즌에 참여한 플레이어분들께서는 익히 아시겠지만 시즌에는 금화, 장비, 정복자 레벨 등 육성하고 획득할 여러 요소들이 있습니다. 그럼 시즌이 종료될 때 이러한 시즌 캐릭터의 진행 정보는 어떻게 되는 것일까요? 간단히 말하자면, 시즌 캐릭터의 진행 정보는 모두 유지할 수 있습니다.
앞으로 비시즌 캐릭터로 플레이하면서 만나볼 수 있는 이번 시즌의 모든 보상 목록은 아래에서 확인하실 수 있습니다.
  • 영웅
    • 시즌 영웅은 비시즌 일반 모드 영웅 및 하드코어 모드 영웅으로 전환됩니다. 해당 영웅을 위한 캐릭터 슬롯을 확보하기 위해 기존의 다른 캐릭터를 삭제할 필요는 없습니다. 현재 시즌 영웅이 차지하고 있는 캐릭터 슬롯은 앞으로도 계속 사용할 수 있으니까요.
  • 금화
    • 시즌에서 획득한 금화는 비시즌 영웅으로 이전됩니다.
  • 정복자 경험치
    • 시즌에서 획득한 정복자 레벨의 총합 대신, 획득한 정복자 경험치의 총량이 비시즌으로 이전됩니다.
    • 예를 들어, 시즌 영웅의 정복자 레벨이 300 이고 기존 비시즌 영웅의 정복자 레벨이 400 일 경우, 시즌 종료 시 비시즌 영웅의 정복자 레벨은 단순 합산 값인 700 이 아닌 그 이하가 되며, 이는 정복자 레벨이 높아질수록 정복자 레벨이 오르는데 더 많은 경험치가 필요하기 때문입니다.
  • 핏빛 파편
    • 금화와 비슷하게, 시즌 종료 시점에서 시즌 영웅이 보유한 모든 핏빛 파편은 비시즌 영웅으로 이전됩니다.
    • 만약 여러분의 비시즌 영웅들이 현재 핏빛 파편을 최대 보유 한도만큼 지니고 있다면, 시즌 종료시 보유한 시즌 영웅들의 핏빛 파편은 일시적으로 비시즌 영웅들의 최대 보유 한도를 무시하고 이전되어 합산됩니다. 이 핏빛 파편을 여러분이 원하는 대로 소모할 수 있지만, 이렇게 합산된 핏빛 파편의 보유 개수가 최대 보유 한도 이하로 내려가기 전까진 추가로 핏빛 파편을 획득하지 못한다는 점을 유의하시기 바랍니다.
  • 아이템
    • 현재 시즌 영웅이 착용하고 있거나 소지품에 있는 아이템은 시즌이 종료되면 비시즌 게임 모드로 해당 영웅과 함께 그대로 이전됩니다.
    • 시즌 영웅들의 보관함에 있는 아이템은 게임 내 우편 시스템을 통해 비시즌 영웅들에게 보내집니다. 시즌이 종료된 이후 처음으로 게임에 접속한 시점부터 30일간 이러한 아이템을 모든 비시즌 영웅을 통해 수령할 수 있습니다. 우편함을 살펴보시려면 게임을 생성 또는 게임에 참가한 후 화면 좌측 하단에 보이는 우편 아이콘을 누르시면 됩니다.
  • 장인 레벨 및 제조법
    • 시즌 영웅들의 장인 레벨이 비시즌 영웅들의 장인 레벨 보다 높다면, 시즌 종료 시 해당 장인 레벨이 비시즌 영웅들의 장인 레벨로 이전됩니다.
    • 비시즌 장인들이 익히지 못한 시즌 장인의 모든 제조법도 마찬가지로 시즌 종료시 비시즌 장인들에게 이전됩니다.
  • 보관함
    • 시즌 중에 구매한 공유 보관함 또는 보관함 탭 중 비시즌 영웅들이 보유하지 못한 것은 위와 마찬가지로 비시즌 영웅들에게 이전되어 적용됩니다.
  • 업적
    • 시즌에서 획득한 업적이나 기록중인 업적 진행 정보는 비시즌 업적 프로필에 자동으로 반영됩니다. 이 작업은 실시간으로 이뤄지며 시즌 종료가 필요한 것은 아닙니다. 업적 점수 또한 시즌 기간 중에 달성한 내역에 맞춰 업데이트됩니다.
  • 시즌 1 보상
    • 시즌 전용 보상인 투구와 어깨와 부위 형상변환은 시즌 1에서 70레벨 영웅을 육성한 모든 플레이어분들에게 개방됩니다. 시즌 영웅이 70레벨에 도달하는 즉시 이 형상변환이 개방되고, 시즌이 종료되기 전에도 시즌과 비시즌 영웅 모두 이 형상변환을 이용할 수 있습니다. 새로운 형상변환을 이용하시려면, 마을의 미리암을 방문하여 형상변환 탭 창을 열어보시기 바랍니다.
모든 영웅과 보상, 진행 정보는 그에 맞춰 비시즌 게임 모드로 이전된다는 점을 참고해주시기 바랍니다. 시즌 일반 영웅들로 획득한 아이템과 금화, 정복자 경험치, 업적, 장인 레벨과 제조법, 보관함 공간, 핏빛 파편은 시즌이 종료되면 비시즌 일반 영웅들로 이전됩니다. 하드코어 또한 마찬가지로, 시즌 하드코어 영웅들로 획득한 모든 것들은 비시즌 하드코어 영웅들로 이전됩니다.

시즌 1 정벌

다른 보상과 달리, 정벌은 시즌이 종료될 때 전환되지 않는데, 그 이유는 비시즌 영웅에겐 정벌이 허용되지 않기 때문입니다. 이는 또한 시즌 중에 달성한 정벌은 비시즌 영웅들의 업적 점수에는 영향을 주지 않는 다는 의미입니다.
하지만 염려하진 마세요. 시즌이 종료된 이후에도 여러분의 프로필 기록 페이지에선 언제든 여러분의 위대한 흔적을 찾아볼 수 있습니다.

시즌 1 순위표

시즌이 종료되면, 모든 시즌 순위표는 초기화되고, 다음 시즌이 시작되기 전까진 새로운 순위표 기록은 제공되지 않습니다. 이전 시즌의 순위표 기록은 게임 내에서 살펴볼 수 있도록 유지됩니다. 새로운 시즌이 시작되면, 순위표의 드롭다운 메뉴를 통해 현재 시즌과 이전 시즌 기록을 오가며 확인하실 수 있습니다.
물론 현재와 과거의 순위표는 이 곳 공식 홈페이지에서도 살펴보실 수 있습니다.
비시즌 대균열 순위표는 시즌 종료에 바로 영향을 받지 않기에 여러분은 계속해서 비시즌 영웅(시즌에서 비시즌으로 전환되는 영웅으로도)으로 순위표 상의 플레이어들과 경쟁할 수 있습니다. 이 대균열 순위표는 시즌 종료 이후에 초기화되며, 여기에 대해서는 추후 세부 정보를 안내해드릴 예정입니다.

시즌과 시즌 사이

시즌 종료 이후 새로운 시즌이 시작되기 전까지 짧은 비시즌 기간이 존재합니다. 이 기간 중에, 여러분은 전환된 보상들과 순위표 상의 기록을 살펴보실 수 있습니다. 어쩌면 이 기간이 여러분의 성취와 전리품을 다시 살펴볼 수 있는 가장 뜻 깊은 시간이 아닐까요?
그럼 언제 시즌1이 종료될까요? 현재 예상하고 있는 가장 이른 시즌 종료 일정은 2015 2 3입니다. (태평양 표준시 기준이며, 정확한 일정은 추후 업데이트 예정) 예기치 못한 문제로 일정은 얼마간 미뤄질 가능성도 있지만, 저희는 최대한 이 일정에 맞춰 시즌을 종료시키려 합니다. 만약 시즌 종료 일정이 변경된다면, 업데이트된 일정을 다시 안내해 드리겠습니다.

시즌 종료를 맞이할 준비가 되셨나요?

시즌1은 어땠나요? 대균열은 몇 단계까지 가보셨나요? 정벌 임무를 몇개나 완수해보셨나요? 첫 시즌에서는 어떤 것이 제일 기억에 남나요?
댓글로 여러분의 경험담이나 의견을 남겨주세요. 이제 시즌2가 얼마 남지 않았습니다.

2014년 12월 23일 화요일

About command『grep』..

(네이버블로그에서 옮겨옴)
2005/08/18 18:55 http://blog.naver.com/jujac/20015983615


About command『grep』..



  • grep
    • : 하나의 파일이나 여러 파일에서 특정 문자열을 찾는다.
  • grep '\' {file-name}
    • : "cho"가 포함된 줄을 출력시킨다.
  • grep 'cho taehyun' {file-name}
    • : "cho taehyun"가 포함된 줄을 출력시킨다.
  • grep '^cho' {file-name}
    • : "cho"가 줄 맨 앞에 있으면 그 줄을 출력시킨다.
  • grep '\.bak$' {file-name}
    • : ".bak"로 끝나는 줄을 출력한다.
  • grep '[Pp]yramid' *
    • : 현재 작업 디렉토리 내에 있는 모든 파일에서 pyramid나 Pyramid를 포함하는 모든 줄을 출력시킨다.
  • grep '[A-Z]' {file-name}
    • : 하나 이상의 대문자가 포함된 포함된 줄을 출력시킨다.
  • grep '[0-9]' {file-name}
    • : 하나 이상의 숫자가 포함된 줄을 출력시킨다.
  • grep '[A-Z]...[0-9]' {file-name}
    • : 대문자로 시작하고 숫자로 끝나는 다섯 문자의 패턴이 포함된 줄을 출력시킨다.
  • grep -w '[tT]est' {file-name}
    • : Test나 test가 포함된 줄을 출력시킨다. (*단어 단위)
  • grep -s "Mark todd" {file-name}
    • : Mark Todd 패턴이 포함된 줄을 찾는다. 하지만 그 줄을 출력시키지는 않는다. 이 옵션은 grep의 exit status를 검사할 때 사용할 수 있다.
  • grep -v 'Mary' {file-name}
    • : Mary가 포함되지 않는 모든 줄을 출력시킨다.
  • grep -i 'sam' {file-name}
    • : 대소문자에 관계없이 모든 줄을 출력시킨다.(예, SAM, sam, Sam, sAm,SaM)
  • grep -l 'Dear Boss' *
    • : Dear Boss가 포함된 모든 파일들의 리스트를 출력시킨다.
  • grep -n 'cho' {file-name}
    • : cho가 포함된 줄을 줄 번호와 함께 출력시킨다.
  • grep "$name" {file-name}
    • : name변수의 값을 확장시킨 다음에 그 값을 갖는 줄을 출력시킨다. 이때 큰따옴표를 사용해야 한다.
  • grep '$5' {file-name}
    • : $5가 포함된 줄을 출력시킨다. 작은 따옴표를 반드시 사용해야 한다.
  • ps -ef | grep "^ *user1"
    • : ps -ef 코맨드의 출력을 grep으로 파이프시킨다. 그러면 grep은 user1로 시작하는 줄을 찾는다. 이 때 user1앞에 0이나 스페이스가 와도 상관없다.

레지스터리에 DLL파일 등록 그리고 제거

(네이버블로그에서 옮겨옴)

2005/08/18 18:55 http://blog.naver.com/jujac/20015983578


레지스트리에 DLL파일 등록

  • regsvr32 {dll-file} /s


레지스트리에 DLL파일 제거

  • regsvr32 {dll-file} /u


웹서버보안관련메모 (at Linux)

웹서버보안관련 메모 (at Linux)


2005/08/18 18:54 http://blog.naver.com/jujac/20015983550

(네이버블로그에서 옮겨옴)


ntsysv 명령으로 불필요한 데몬을 모두 죽인다.
◎ telnet과 FTP서비스에 대한 IP Address의 통제권한 부여
( TCP Wrappers를 이용 )

a. hosts.deny : 접속을 차단
■ vi Edit Console
=====================================================
#
# hosts.deny This file describes the names of the hosts which are
# *not* allowed to use the local INET services, as decided
# by the '/usr/sbin/tcpd' server.
#
# The portmap line is redundant, but it is left to remind you that
# the new secure portmap uses hosts.deny and hosts.allow. In particular
# you should know that NFS uses portmap!
in.telnetd:ALL
in.ftpd:ALL
=====================================================

b. hosts.allow : 접속을 허용
■ vi Edit Console
=====================================================
#
# hosts.allow This file describes the names of the hosts which are
# allowed to use the local INET services, as decided
# by the '/usr/sbin/tcpd' server.
#
in.telnetd:123.123.123.123
in.ftpd:123.123.123.123
=====================================================

c. 변경후 xinetd restart필요
■ vi Edit Console
=====================================================
[root@ns etc]$ cd /etc/rc.d/init.d
[root@ns init.d]$ ./xinit.d stop
Stoping xinetd: [OK]
[root@ns init.d]$ ./xinit.d start
Starting xinetd: [OK]
[root@ns init.d]$ _
=====================================================


◎ 포트제어
a. setup명령에 의한 firewall configuration 제어
b. /etc/services 파일 직접제어



W3C libwww & libxml libraries install

(네이버블로그에서 옮겨옴)

2005/08/18 18:39 http://blog.naver.com/jujac/20015982927


W3C libwww & libxml libraries install

at Unix / Linux

W3C libwww libraries

w3c-libwww-5.4.xx.tar.gz
 tar xfvz w3c-libwww-5.4.xx.tar.gz
 cd w3c-libwww-5.4.xx
 ./configure --prefix=/usr --with-zlib --with-mysql
 make
 make install

=======================================


W3C libxml libraries

libxml2-2.6.xx.tar.gz
 tar xfvz libxml2-2.6.xx.tar.gz
 cd libxml2-2.6.xx
 ./configure --prefix=/usr --desable-shared
 make
 make install



[SQLite] autoincrement reset - 시퀀스 초기화(or 재설정)

SQLite autoincrement reset - 시퀀스 초기화(or 재설정)

  • UPDATE SQLITE_SEQUENCE SET seq = N WHERE name = 'TABLE_NAME';


[포럼게시글 펌] 역인덱스 구조에서의 AND 검색의 속도 향상. (2007년)

(네이버블로그에서 옮겨옴)

2007/08/14 00:33 http://blog.naver.com/jujac/20040528894

역인덱스 구조에서의 AND 검색의 속도 향상.

글쓴이:jinyedge
조회수:1094

요즘에 대용량 데이타베이스를 다루게 되었습니다. 쉽게 말하자면 웹문서 검색엔진입니다.
크롤러와 인덱서는 java로 만들었지만 인터페이스단에서는 php를 사용하고 데이타베이스로는 mysql을 사용합니다. 아래는 현재 개발중인 검색엔진의 현황입니다.
- 저장된 문서의 갯수: 61만개
- 인덱싱된 단어의 갯수: 4500만개
- 데이타베이스 크기: 1기가 바이트
- cpu: p4 2.4
- ram: 512
- hdd: ide 7200
그리고 데이타베이스는 mysql 4.015 바이너리 버전을 사용하고 있습니다.

----------------------
데이타베이스의 테이블의 경우 크게 나누면 다음의 2개로 구성됩니다.
(실제로는 전체 용량의 감소과 검색 속도의 향상을 위해서 구조가 더 복잡하지만 여기서는 단순화해서 설명하겠습니다)

  1. kw_table: 각 웹문서로부터 뽑아낸 키워드가 저장되어 있는 테이블입니다. 일종의 역인덱스 파일이라고 할 수 있죠. 각 키워드는 자신이 속한 웹문서의 번호와 함께 저장되어 있습니다.
  2. html_table: 원래의 웹문서가 저장되어 있습니다.

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

현재 이런 구조에서 단일어 검색의 경우는 보통 0.2초 이하에 결과가 나옵니다.
아마 지금보다 데이타가 더 많다고 해도 결과는 비슷하리라 생각합니다. 그런데 문제는 and 검색의 경우입니다.

현재 AND 검색의 경우는 보통 1초에서 5초까지 걸립니다. 물론 이것도 결과 갯수를 500개로 제한을 걸어둔 상태입니다. AND 검색의 경우는 다음의 두가지 방법을 시도해 봤습니다.


1) kw_table에서 교집합을 구하는 방법

- 예를 들어서 '게임 정보' 라는 검색어를 사용하여 검색을 하는 경우

먼저 kw_table에서 '게임'에 해당하는 웹문서의 번호를 구하고 다시 kw_table에서 '정보'에 해당하는 웹문서의 번호를 구한 다음 이것들의 교집합을 구하는 것입니다. 하나의 sql 문으로 표현하자면 다음과 같은 형식이 되겠죠.
select html_idx, count(*) cnt from kw_table where kw in('게임', '정보')
group by html_idx having cnt = 2 limit 0, 15;
그러나 이 경우는 일단 group by 에서 많은 부하가 걸리고 해당되는 row의 갯수를 구하기 위해서 모든 row를 가져와야 하는 문제가 있어서 포기했습니다.


2) kw_table로부터 임시 테이블을 만들고 이것을 join하여 순차검색을 하는 방법

- 예를 들어서 '게임 정보' 라는 검색어를 사용할 경우
먼저 '게임'에 해당하는 웹문서 번호를 임시 테이블로 만들고 이것을 다시 html_table과 join을 한 다음 '정보'라는 키워드가 들어있는 row를 순차검색으로 뽑아 냅니다. 실제 sql 문은 다음과 같은 형태가 되겠죠.
create temporary table tmp(html_idx int) select html_idx from kw_table where kw = '게임';
select * from html_table a, tmp b where a.html_idx = b.html_idx and kw like '%정보%';
사실 현재는 이 방법을 사용하고 있습니다.

순차검색을 하기는 하지만 mysql의 경우 게시판에서 내용검색을 한다고 해도 pc급 서버에서도 1만개 정도의 게시물은 1초 이하로 검색이 완료되기에 순차검색을 한다고 해도 별 무리는 없다고 봅니다.

현재는 처음 kw_table에서 가져오는 tmp 테이블의 데이타를 500개로 제한하고 있습니다.
그러니 현재로서는 최대 500개를 join하고 순차검색을 하는 형태입니다.

실제로 이 방식의 경우는 group by에 의한 교집합을 구하는 방식보다 빠르고 전체 row 갯수를 구하기 위해 일단 모든 row를 가져와야하는 불합리한 점도 없지만 임시 테이블 생성과 join에서 부하가 걸리더군요.

임시 테이블의 경우는 in-memory 테이블이 라서 부하가 걸리지 않으리라 생각했는데 의외로 시간을 소모하는 경우가 있더군요. 그리고 join의 경우는 대부분의 시간을 잡아먹는 속도저하의 주범이죠.

제 생각에는 join의 경우는 데이타의 분포형태와도 관련이 있는 것 같습니다.
아마 하드드라이브의 헤드가 움직이는 범위가 클 수록 join에서의 속도저하가 심해지지 않나 싶습니다.

그리고 and 검색에서 제한을 거는 것 자체에는 문제가 없다고 봅니다.
제가 알기로는 대부분의 검색엔진이 and 검색의 대상을 어떤 형태로든 제한을 하고 있습니다. 제가 생각하기에는 현재 사용하고 있는 방식으로도 제한의 갯수를 1만개까지 늘릴 수 있다면 아무런 문제가 없다고 봅니다.

하지만 현재 500개의 제한으로도 충분한 속도가 나오지 않기 때문에 고민 중이죠.
아무튼 여기까지가 제가 현재 검색엔진을 개발하면서 겪고 있는 문제점입니다.


----------------------
현재 제가 생각하는 해결 방식은 일단 하드를 scsi로 교체하여 하드드라이브를 읽는 속도를 높이는 것과 RAM을 늘리고 일부 테이블을 RAM에 올리는 것입니다.

모든 테이블을 램으로 올릴 수는 없겠지만 join시에 속도저하의 주범이 되는 테이블을 RAM으로 올리는 것은 가능합니다. 이것으로 속도를 상당한 정도로 향상시킬 수 있다고 생각은 합니다.

아무튼 현재 제가 생각하는 방식은 하드웨어의 성능을 높이는 방향입니다.

그러나 이외에 제가 생각해낸 데이타 구조나 쿼리의 방법이 완전히 틀린 것은 아닐까하는 생각도 하고 있습니다. 그래서 이런 경우에서 작업을 해보신 분들의 조언을 구합니다. 요즘 저의 생각은 다음의 4가지로 표현할 수 있습니다.


  1. 역인덱스 구조에서의 AND 검색시에 임시 테이블이나 join을 쓰지 않고 처리할 수 있는 방법이 있을까요?
  2. 만약 현재의 db구조를 유지한다면 어떤 형태로 쿼리를 구성하는 것이 최선일까요?
  3. mysql로는 무리가 있으니 다른 데이타베이스로 교체하는 것이 옳을까요?
  4. 아니면 데이타베이스를 사용하는 것 부터가 무리이니 차라리 파일 시스템으로 가야 할까요?



저와 비슷한 경험을 갖고 계신 분들이 계시다면 고견을 들려주시면 감사하겠습니다.


> navyism
저도 검색엔진에 참 관심이 많아 이것저것 해보았는데요...
캐시 테이블을 하나 만들고 그것을 잘 활용해보는 쪽으로 생각을 하고 있습니다.
그런데 이것도 검색대상이 자주 업데이트 되는 경우라면 그다지 좋은 방법은 아닐듯 싶고요...
대형 검색엔진들의 검색 알고리즘이 참으로 궁금하네요...
하드웨어로 카바하는 것도 아닐테고 말이죠....
의견을 드린다면 4번은 그다지 좋은 방법은 아닐것 같습니다^^;;
10/09 22:28:18 211.202.28.80


> 익명
이런... 그렇지 않습니다. 4번이 좋은 예 이지요.. 흠.. 검색엔진에 관심이 많으시다면 잘 아실텐데요.
뭐 어쨌든... 결론만 이야기 해서... 저희회사는 LDAP + Informix를 사용하여 개발을 했습니다.
뭐.... 쩝... 금방 바닥날 이야기 라서 솔직히 말하는거지만.. 전 보조 프로그래머 이고...
저희 수석 엔지니어 분 께서 전체적인 설계를 구현하셨는데.. 처음엔 LDAP 와 PostgreSQL 을 사용했습니다.
회사이름 이야기 하면 광고가 될테니.... 입사한지 이제 1달 되었습니다 ㅡㅡ;
지금 제가 하는 일은 팀장님의 지시로 lucene 를 열심히 보고 있습니다.
기본 구조에 대하여는 상당히 확실한 감을 잡을 수 있다고 해서 현재 열심히 공부 중 입니다.
http://jakarta.apache.org/lucene/docs/index.html 에서 보실 수 있습니다.
10/09 23:20:32 61.78.224.220


> 별거없음
lucene도 마찬가지지만, 데이터가 입력되는 시점에 인덱스를 단어단위로 생성하거나
글자 한개 단위로 생성하거나 하는 식으로 작성하고, 해당 index를 메모리로 올리면 끝입니다.
상당히 간단하죠?^^
10/09 23:52:04 211.49.30.51


> jinyedge
캐시의 경우는 mysql 4.0 버전의 경우 쿼리캐시가 지원되니 그것으로 충분하다고 생각합니다.
실제 단일어 검색이던 AND 검색이던 현재 일단 캐시에 저장이 되면 대부분 0.0x초가 나옵니다.
쿼리 캐시 사이즈만 맘껏 할당할 수 있다면 캐싱된 데이타가 많아질테고 리부팅하지 않는한 속도야 빠르겠죠.
실제로 사람들이 검색하는 검색어라는게 대부분 비슷하니 캐시의 적중률도 상당히 높고 말입니다
그리고 파일 시스템의 경우 빠르기는 하겠죠. 문제를 푸는 데에 보다 자유롭게 여러 방법을 사용할 수도 있고 말입니다.
단지 파일시스템을 db로 쓴다면 인터페이스 단에서 php 사용을 포기해야겠죠.
웹프로그램에서 직접 파일을 악세스하려면 c로 cgi를 구성하는 것이 좋겠죠.
아니면 파일시스템을 관리하는 서버를 하나 만들고 php에서 이쪽을 접속하던가 하는 방법이 있겠는데 이거야 mysql의 심플 버전을 만드는 것과 비슷하겠죠.
아무튼 파일시스템으로 가게 되면 여러가지 점에서 어려워집니다. 그래서 현재는 가급적이면 db를 사용하려고 하는 거죠.
물론 db를 사용하는 방식으로는 전혀 비전이 없다면 파일시스템을 심각하게 고려를 하는 수밖에 없겠지만...
10/09 23:52:12 218.147.245.143


> 별거없음
어려운건 없고, 검색조건에 대해 검색영역을 메모리에 올려둔 인덱스 테이블로 부터 받고, 그것을 쿼리에 조건으로 잡고, 추가 조건을 붙여서, 쿼리 생성 본데이터를 뺍니다.
10/09 23:54:24 211.49.30.51


> miplus
검색엔진에서는 DB 잘 사용하지 않습니다. 별도로 파일구조나 기타구조로 인덱싱하죠.
10/10 9:53:21 210.182.140.150


> luna
검색엔진은 데이터를 단어,형태소별로 파싱해서 인덱싱 합니다. 그리고 최적화된 자기만의 DB를 쓰죠..
10/10 13:01:04 203.251.146.109


> 찌뉘
luna님 의견에 한표.. 최적화된 자기만의 DB와 쿼리문장이 제일 좋은 해결책인것 같습니다.
10/10 13:21:39 202.33.246.18


> jinyedge
DB를 쓰던 뭐를 쓰던 검색엔진의 기본은 같습니다. 그리고 AND 검색의 경우도 결국 문제를 압축하면 - 역인덱스 구조라면 말입니다 - 교집합을 구하는 방식으로 가느냐 join을 하는 방식으로 가느냐일 겁니다.
파일시스템으로 간다고 해도 문제가 크게 달라지지는 않을 것입니다.
단지 어려움이 있다면 DB의 용량과 속도에서 오는 제약을 충족하려니 어려워지는거고 저희 같은 경우는 더욱 작은 용량으로 만들려고 하니깐 더 어려워지겠죠.
현재 저희는 용량의 컷트라인을 문서 100만개당 1G로 잡고 있습니다.
그런데 아무래도 AND 검색의 속도를 높이기 위해서는 인덱싱 파일이 하나 더 필요할 것 같아서 용량을 늘려 보기로 생각을 하고 있습니다. 용량을 좀 희생하고 속도를 높인다는 거죠.
아마 30% 가량 데이타베이스의 크기가 증가할 것 같습니다.
그리고 검색엔진 공부하시는 분들을 위해서 저도 문서 하나를 추천하겠습니다.
다음의 문서는 구글의 내부구조에 관해서 논하고 있는 문서입니다.
꼭 검색엔진을 만드려는 분들이 아니라도 대용량 데이타베이스에서의 검색에 관심이 있는 분들이라면 그런대로 유용할 것입니다.
http://www7.scu.edu.au/programme/fullpapers/1921/com1921.htm
10/10 13:45:46 218.147.245.143


> jinyedge
익명// 한가지만 물어보겠습니다. 귀사에서 개발한 검색엔진이 현재 저장하고 있는 문서의 갯수는 얼마나 됩니까?
아마 이 정도는 대외비라고 할 것까지는 없을 듯한데 알려 주시면 감사하겠습니다.
제가 생각하기에 informix로 가능하다면 mysql이라고 해서 안될 이유가 없을 것 같군요.
10/10 13:50:33 218.147.245.143


> 11
url 가르쳐 주실수 있나요..?
10/10 17:12:23 61.104.129.100


> 더마린
입력시 인덱싱 해서 별도의 구조로 메모리상에 올리고, 실 데이터는 db에 저장하는게 평균적으로 일정하고 높은 퍼포먼스에, 데이터의 증가와 관련없는 결과를 내올 수 있습니다.
10/10 17:15:09 211.232.135.86


> 더마린
안정성 측면은 얘기되어지고 있지 않은데, 데이터의 사이즈가 어느정도 되고, 1000만번에 한번 안깨지게 하는게 보통 일이 아닙니다.
이를 보장하기 위한 수단과 대용량을 염두해두어야 하는 상황이라면
실데이터는 dbms로 넘기는게 적절한 선택이 될 수 있다는 것도 고려하시기를..
10/10 17:18:16 211.232.135.86


> 전영규
대충 마무리 되는 것 같네요.
jinyedge 님, 저도 만들었던 검색엔진을 개선해서 제 아이디어를 실험해 보려 합니다.
일단 님의 생각과 저도 비슷한 생각을 하고 있습니다.
다만, 좀 더 최적화시키는 자잘한 생각을 더하고 있구요.. 아무래도, 획기적인 개선안은 힘들지 않을까 싶습니다.
링크하신 문서도 도움은 되는데, 님도 결정적 도움을 받지 못하셨듯, 일반 참고정도가 아닐까 싶습니다..
(읽어보려면 시간들어서 .. -_-; 번역기나 하나 구해야 겠습니다.)
님도 계획에 있겠지만, 더 중요한 건 형태소 분석이 아닐까 싶습니다.
다중검색에서 쿼리문을 최적화시키는 데는 형태소분석이 필수조건일 수도 있다는 생각입니다.
그래야 풀 인덱스를 타면서 좀더 빠른 결과를 낼 수 있으니까요..
형태소 분석에 대해 나름대로 연구하는 중이긴 한데, 잘 될지는 모르겠군요. 님은 어떤지 궁금합니다.
어느 대학 교수님이 공개했다는 라이브러리는 몇번 보긴 했는데, 라이센스문제도 있고 별로 효용성은 없어 보이더군요.
-- jeon.
10/10 19:42:43 221.153.4.21


> 익명
jinyedge// 문서의 수는 2003.10.10 20:45 현재 251,374,506 이네요...
10/10 20:48:57 61.78.224.220


> 별거없음
형태소분석이라... 상용검색엔진 직접 만들어보신 분은 아시겠지만,
한글이란 특성 때문에 단위를 형태소 단위로 인덱싱한다는 것 뿐이지, 형태소분석이라 할만한 특이점은 없습니다.
'형태소분석'이란 작업은 자연어검색을 위한 사전작업때 사람이 손으로 일일이 수행하는 것 말고는 형태소분석이란 것은 아예 존재하지 않습니다. 포공, 카이스트 출신의 자연어석박사분들께 물어보시길..
lucene을 뜯어보거나, 검색엔진 작업을 해보시면 아시겠지만 단위별(형태소든, 띄어쓰기단어든) 인덱싱(의미및 구조에 따른 인덱싱이 아닌, 일괄적용 알고리즘의 인덱싱입니다)이
검색엔진의 주된 모든 작업이고, 이후의 작업은 Tree쓰던, DB쓰던 별거없음..
file DB로 0.1초 빠르게 만들게 하기 위해 1-2개월씩 보내면 대략 낭패~
10/10 21:52:14 211.49.30.191


> 별거없음
검색엔진 만들고 싶은 사람은 다른거 필요없이 lucene을 한번 뜯어보면 아햏햏~
10/10 21:53:55 211.49.30.191


> 전영규
별거없음님, 경험이 많으신 것 같습니다 ^^
형태소분석에 대해서는 사실 용언분석까지는 아니고, 복합명사나 조사분리 정도로 된다고 보구요..
그것만으로도 데이타나 코드가 좀 필요하더군요 -_-; 일단 생각대로 구현해 보고...
lucence 는 소스가 너무 커서 일일히 볼 시간이 없습니다. -_-;
대충 봤는데, '속도' 보다는 '기능성' 에 치중한 것 같더군요. 그런데 .. 저는 속도에 더 관심이 많습니다.. ^^;
-- jeon.
10/11 0:06:56 221.153.4.21


> jinyedge
익명// 좋은 정보 감사합니다.
10/11 10:18:29 61.84.19.130


> jinyedge
11// 그다지 비밀이라고 할 것도 없죠. http://www.skouter.com 입니다.
10/11 10:19:35 61.84.19.130


> jinyedge
전영규// 처음에 개발초기에서는 형태소 분석을 저도 중요하다고 생각했습니다.
그러나 지금은 아닙니다. 그냥 -에, -의, -을, -를 등의 조사 처리만 하고 그외의 복합명사 같은 건 무시하려고 합니다.
기본적으로 형태소 분석의 프로그램적인 처리는 불가능하다는 게 제 입장입니다. 아래에서 강산에의 경우 무슨 차이가 있습니까?
1. 아름다운 우리 강산에 한 그루 나무를 심는다면..
2. 강산에 (가수) 프로필.
우리는 눈으로 보고 바로 차이를 알 수 있죠. 2개의 강산에는 서로 다른 겁니다.
그러나 프로그램적으로 이 차이를 알 수 있나요? 실제 형태소분석 기술을 자랑하는 모 검색엔진에서는 강산에라는 키워드로 검색하면 우리강산 좋은 강산 이라는 식의 웹페이지들만 잔뜩 나오죠.
이것은 기본적으로 검색을 하려는 사람이 입력하는 키워드를 지나치게 가공/변형하거나 웹문서의 인덱싱 과정에서 키워드들을 지나치게 가공/변형한 결과입니다. 이런식으로 인위적인 가공을 하게 되면 특정 상황에서만 좋은 결과를 얻게 마련입니다.
한가지 예를 더 들겠습니다. 우리가 인하대학교 웹사이트를 찾을 때 어떤 검색어를 입력하나요? 아마 다음의 검색어들이 가능할 겁니다.
• 인하, 인하대, 인하대학교, 인하 + 대학교
그럼 인하대학교라는 단어 하나에서 꼭 이 많은 걸 뽑아내야만 인하대학교를 위의 검색어로 검색할 수 있을까요?
저는 그렇지 않다고 생각합니다.
사람들이 인하대학교를 인하대라고 지칭하기도 한다면 즉 그 말이 실제로 쓰인다면 인하대로 검색을 해도 인하대학교 웹페이지를 찾을 수 있는 겁니다. 물론 여기에는 몇가지 전제조건이 붙기는 하지만 말입니다.
뭐.. 아무튼 지금은 형태소 분석에는 관심이 없습니다. 가능하다고 생각하지도 않고 가능한지 몰라도 별 필요는 없다는 게 제 입장입니다.
그냥 여기까지만 하도록 하겠습니다.
10/11 10:36:20 61.84.19.130


> 전영규
jinyedge님, 저와 생각이 다르시군요. ^^
-- jeon.
10/11 12:58:08 221.153.4.21


> 나그네
형태소 분석 같은 시도가 없다면 검색엔진은 단지 인덱스 생성기에 지나지 않을 것 같다는 생각이 드네요.
그 이상의 발전을 기대할 수 있을까요?
10/11 15:06:44 211.245.200.32


> jinyedge
나그네// 단지 인덱스 생성기라... 글쎄요... 검색엔진 생각보다 재밌는 부분이 많습니다.
한국 사람이 검색을 한다면 대부분 옥션을 입력하면 www.auction.co.kr 이 최상위에 나오기를 기대하고 mbc를 입력하면 www.imbc.com이 나오기를 기대하고 다음을 입력하면 www.daum.net 이 나오기를 기대하겠죠.
그런데 이렇게 나오게 한다는게 말처럼 쉽지가 않죠.
갖가지 랭킹조작을 하려는 시도가 난무하는 공간이 인터넷이죠.
다음의 예는 구글에서 옥션이라는 검색어를 입력하면 나오는 웹문서 중의 하나입니다.
---------------------------
이양 이양 이양 이양 이양 이양 이양 이양 이양 ...
... 최신주드한국뽀르노한국성인동영상홍콩아마추어변태섹 스벅스뮤직세이클
럽넷마블네이버다모임한미르엠파스엽기라이코스한게임스포츠조선크레이
지아케이드스포츠서울일간스포츠아이러브스쿨게임옥션바람의나라지오피
아 ...
---------------------------
이런 문서가 상위권에 나온다는 건 좀 문제가 있겠죠. 일차로 이 따위 문서로 랭킹 조작을 하는 사람이 문제가 있겠지만 말입니다.
그리고 인덱싱이 검색엔진의 전부는 아닙니다. 크롤러에서도 재밌는 문제는 많습니다.
예를 들자면 옥션의 경우 현재 야후, 한미르, 드림위즈, 천리안, 조선일보 등에 서브 도메인 형태로 들어가 있습니다.
사실은 동일한 사이트인데 이름만 다른 케이스죠. 이때 이 문서들을 모두 저장을 해야 할까요?
서브 도메인 10개면 중복 문서 10개라는 건데 이런 건 어떻게 처리해야 될까요?
만약 중복문서라고 저장을 안 하기로 했다면 무엇을 남겨야 할까요?
뭐.. 생각하기에는 www.auction.co.kr이 오리지날이니 이것만 남기자고 생각할 수도 있겠는데 이걸 프로그램으로는 어떻게 구분하나요?
먼저 저장된 걸 기준으로? 만약 auction.chol.com 이 먼저 저장되면 어떻게 하나요?
그럼 www.auction.co.kr은 저장이 안 될텐데... 뭐.. 이런 식의 문제가 끝도 없이 나타납니다.
그리고 이런 문제에 대해서 정책을 수립하고 실제 프로그래밍을 통해서 그 정책을 구현하는 게 검색엔진을 만드는 작업이겠죠.
또 이런 부분들이 제가 생각하는 검색엔진의 재밌는 부분이라는 거죠.




자주 쓰는 MySQL 명령어 정리 (2007년)

(네이버블로그에서 옮겨옴)

2007/05/17 20:38 http://blog.naver.com/jujac/20037219564

MySql 기본 사용법

리눅스에서 직접 로그인 또는 텔넷으로 로그인 한 후 다음과 같은 명령들을 이용하여 MySql을 실습해 볼 수 있습니다.

1. 해당 디렉토리 찾아가기
$ cd /
$ cd usr/local/mysql

2. mysql 처음 사용시 해야할 것
- mysql의 root사용자의 패스워드를 다음과 같이 설정하고 mysql를 재기동하도록 합니다.
$ mysql -u root
mysql> use mysql;
mysql> show databases;
mysql> show tables;
(여기서 db, user 테이블을 주목해 두어야 함.)
mysql> select * from db;
mysql> select * from user;
mysql> update user set password=password('******') where user='root';
mysql>\q;
$ mysqladmin -u root reload

3. mysql 재기동
$ mysqladmin -uroot -p reload
Enter password : ******
위의 패스워드는 MySql에서 사용하는 패스워드입니다.


4. 데이터베이스의 생성

  • $ mysqladmin -uroot -p create db명
  • Enter password : ******


5. 데이터베이스의 삭제
$ mysqladmin -uroot -p drop db명
Enter password : ******

6. 특정 db 사용자 권한 설정 및 새로운 사용자 등록
$ mysql -u root -p
Enter password : ******
mysql> use mysql;
mysql> insert into db values ('%','db명', '사용자ID', 'y','y','y','y','y','y','y','y','y','y');
mysql> select host, db, user from db;
mysql> insert into user (host, user, password) values ('localhost', '사용자ID', password('패스워드'));
mysql> select host, user, password from user;
mysql> \q


※ 지금부터는 linux3s1 사용자(패스워드는 111111으로 가정)가 linux3 데이터베이스를 사용한다는 조건하에서 예시를 들어 설명합니다.


7. mysql 의 실행
$ mysql -u linux3s1 -pEnter password : ******

8. 어떠한 데이터베이스가 있는지 확인
mysql> show databases;

9. 사용할 데이터베이스를 선택
mysql> use linux3s;

10. 특정 데이터베이스안에 어떠한 테이블들이 있는지 확인
mysql> show tables;


11. table 생성/수정/삭제

  ⑴ linux3s 데이터베이스에 imsi 테이블을 CREATE TABLE을 이용하여 생성한다.
mysql> create table imsi(
-> name CHAR(8),
-> id VARCHAR(10) NOT NULL,
-> url VARCHAR(40),
-> email VARCHAR(40),
-> milage INT(11),
-> level CHAR(2),
-> PRIMARY KEY(id) );
  ⑵ desc 명령으로 imsi 테이블의 구조 명세를 살펴보자.
mysql> desc imsi;
  ⑶ 테이블 내용을 수정하려면 ALTER TABLE 문을 이용한다.
mysql> alter table imsi change column id id varchar(12) NOT NULL;
mysql> desc imsi;
  ⑷ imsi 테이블을 삭제하려면 DROP TABLE문을 사용한다.
mysql> drop table imsi;
mysql> show tables;
  ⑸ mysql client를 이용하지 않고 데이터베이스내에 테이블을 생성하는 방법
아래의 SQL문을 imsi.sql이라는 파일로 저장한다.
create table imsi(
    name CHAR(8),
    id VARCHAR(10) NOT NULL,
    url VARCHAR(40),
    email VARCHAR(40),
    milage INT(11),
    level CHAR(2),
    PRIMARY KEY(id) );

이제 계정의 커맨드 라인에서 아래와 같은 명령을 내리면 mysql client를 통해 linux3s 데이터베이스에 연결하지 않고도 데이터베이스내에 imsi 테이블을 생성.

아래의 명령은 linux3s1라는 사용자로 linux3s 데이터베이스에 연결하여 imsi.sql 파일에 담긴 sql문을 실행한다는 의미이다.


  • $ mysql -u linux3s1 -p linux3s < imsi.sql
  • Enter password : 111111



12. INSERT 명령문으로 5개의 데이터를 imsi 테이블에 삽입해 보자.
mysql> insert into imsi (name, id, url, email, milage, level)
-> values ('이상군', 'server', '815server.net', 'master@815server.net', '1000', 'A');
mysql> insert into imsi (name, id, url, email, milage, level)
-> values ('김재현', 'regist', 'dosa.com', 'master@dosa.com', '1500', 'B');
 
mysql> insert into imsi (name, id, url, email, milage, level)
-> values ('마준석', 'you', 'youiwe.co.kr', 'master@youiwe.co.kr', '2000', 'C');
 
mysql> insert into imsi (name, id, url, email, milage, level)
-> values ('김대수', 'iwe', 'youiwe.co.kr', 'master@youiwe.co.kr', '1500', 'B');
 
mysql> insert into imsi (name, id, url, email, milage, level)
-> values ('한용수', 'yshan', 'hanserver.com', 'master@hanserver.com', '2500', 'E');

13. SELECT 문으로 확인해 보자.
mysql> select * from imsi;

14. SELECT 문으로 level이 B인 사용자의 이름과 아이디를 출력해 보자.
mysql> select name, id from imsi where level='B';

15. DISTINCT 옵션을 이용하여 imsi 테이블에 총 몇 종류의 사용자 level이 존재하는지 알아보자.
mysql> select distinct (level) from imsi;

16. WHERE 문을 이용하여 milage가 1500 이상이면서 level이 'B'인 사람의 이름과 아이디, url을 출력해 보자
mysql> select name, id, url from imsi where milage>1500 AND level='B';

17. ORDER BY문을 이용하여 검색 결과를 정렬하여 보자
milage가 2000 이상인 사람의 이름과 아이디, milage를 milage가 높은 순서대로 출력
mysql> select name, id, milage from imsi where milage > 2000 order by milage DESC;

18. 문자열을 포함하여 검색
mysql> select name, '님의 milage는 ', milage, '점입니다.' from imsi?? where milage >= 2000 order by milage;

19. 산술식을 이용하여 출력
mysql> select name, id, email, milage+200 from imsi where id='yshan';

20. 그룹함수를 이용
그룹함수를 이용하면 필드 값의 평균이나 최대, 최소, 또는 해당 조건을 만족하는 레코드가 몇 개 인지 알 수 있으므로 수치를 값으로 갖는 필드에 대한 통계치를 구할 때 유용하다.
count(필드명) //조건을 만족하는 레코드의 개수
sum(필드명) //해당 필드의 합
min(필드명) //해당 필드의 값 중 최소값
max(필드명) //해당 필드의 값 중 최대값
avg(필드명) //해당 필드의 평균값
mysql> select count(*) from imsi where level='B';
mysql> select count(*) from imsi where name like '%박%';
mysql> select count(*) from imsi where name like '박%';
mysql> select count(*) from imsi where name like '전_';
mysql> select count(*) from imsi where name like '전__';
where date between '2001-07-10' and '2001-08-30';


21. 자료의 갱신
mysql> update imsi set name='전세정' where name='마준석';

22. 특정 레코드의 삭제
mysql> delete from imsi where name='전세정';


백업과 복구

· 데이터베이스의 백업(backup)과 복구(restore)는 매우 중요하다.

MySQL에서는 mysqldump라는 파일을 실행하여 데이터베이스내의 데이터를 외부 파일로 저장할 수 있다. mysqldump는 mysql 디렉토리 밑의 bin 디렉토리에 존재하며 아래와 같은 명령어를 통해 백업을 수행한다.

mysqldump -u [user_name] -p [백업할 db_name] > [외부로 저장할 파일명]


23. linux3s? 데이터베이스를 백업해 보자.
$ mysqldump -u linux3s1 -p linux3s > linux3s_backup.sql
Enter password : ******

24. 백업된 파일의 확인
$ ls -l linux3s_backup.sql

25. 위 명령의 실행 결과 생성된 linux3s_backup.sql 파일의 내용을 확인한다.
$ cat linux3s_backup.sql

mysqldump 명령으로 백업된 데이터베이스는 해당 데이터베이스내에 있는 테이블의 구조를 정의한 데이터 정의문과 INSERT 문과 같은 데이터 조작문의 SQL 형태로 저장되어 있다.

이렇게 SQL 형태로 자장되면 아래와 같은 명령으로 쉽게 데이터를 복구할 수 있다. 또한 SQL은 데이터베이스의 표준언어이므로 MySQL이 아닌 다른 database server에 해당 database를 이식하려 할 때에도 호환성에 의한 문제가 거의 발생치 않는 장점이 있다.


26. 필요에 따라 linux3s_backup.sql 파일의 내용을 수정한 후 다음과 같은 방법으로 복구한다.
$ mysql -u linux3s1 -p linux3s < linux3s_backup.sql
Enter password : ******


※ 컬럼의 유형

○ 컬럼(Column)
- 데이터베이스를 구성하는 최소단위
- 컬럼들이 모여서 테이블(Table)을 구성

○ 컬럼의 유형

TINYINT
·부호 있는 정수 -128 ∼ 127
·부호 없는 정수 0 ∼ 255
·1 Byte

SMALLINT
·부호 있는 정수 -32768 ∼ 32767
·부호 없는 정수 0 ∼ 65535
·2 Byte

MEDIUMINT
·부호 있는 정수 -8388608 ∼ 8388607
·부호 없는 정수 0 ∼ 16777215
·3 Byte

INT 또는 INTEGER
·부호 있는 정수 -2147483648 ∼ 2147483647
·부호 없는 정수 0 ∼ 4294967295
·4 Byte

BIGINT
·부호 있는 정수 -9223372036854775808 ∼ -9223372036854775807
·부호 없는 정수 0 ∼ 18446744073709551615
·8 Byte

FLOAT
·단일 정밀도를 가진 부동 소수점
·-3.402823466E+38 ∼ 3.402823466E+38

DOUBLE
·2 배 정밀도를 가진 부동 소수점
·-1.79769313486231517E+308 ∼ 1.79769313486231517E+308

DATE
·날짜를 표현하는 유형
·1000-01-01 ∼ 9999-12-31

DATETIME
·날짜와 시간을 표현하는 유형
·1000-01-01 00:00:00 ∼ 9999-12-31 23:59:59

TIMESTAMP
·1970-01-01 00:00:00부터 2037년 까지 표현
·4 Byte

TIME
·시간을 표현하는 유형
·-839:59:59 ∼ 833:59:59

YEAR
·년도를 표현하는 유형
·1901년 ∼ 2155년

CHAR(M)
·고정길이 문자열을 표현하는 유형
·M = 1 ∼ 255

VARCHAR(M)
·가변길이 문자열을 표현하는 유형
·M = 1 ∼ 255

TINYBLOB & TINYTEXT
·255개의 문자를 저장
·BLOB : Binary Large Object의 약자

BLOB &TEXT
·63535개의 문자를 저장

MEDIUMBLOB & MEDIUMTEXT
·16777215개의 문자를 저장

LONGBLOB & LONGTEXT
·4294967295(4Giga)개의 문자를 저장




MySQL 인덱스 (2004년)

MySQL 인덱스


1. 인덱스를 검사하는 법.
explain select * from Table_Name where A='a' and B='b' order by C,D,E ;
해당 쿼리문이 인덱스를 타는지 안타는지 알기 위해서는 쿼리문 앞에 explain을 붙여주면 인덱스를 타는지 안타는지 알 수 있습니다.
type의 결과값이 ALL일 경우 인덱스를 타지 않고 있습니다.
range,index등일 때 인덱스를 타고 있습니다.
(system, const, eq_ref, range,index, ALL, fulltext)
key의 값이 해당 쿼리문이 타고 있는 인덱스입니다.


2. 경우의 수가 작은 것은 인덱스를 타지 않습니다.
가령 특정 테이블에서 성별을 구분하는 테이블이 있고, 이 테이블에서 성별로 구분해서 보여주는 경우가 많다고 해서 성별을 나타내는 필드에 인덱스를 걸어주어도 인덱스를 타지 않습니다.
인덱스는 결과값이 1/3미만일 경우에만 인덱스를 탑니다. 그러므로 성별같은 경우에는 인덱스를 걸어주는 것이 테이블의 용량만 키우는 결과이기 때문에 인덱스를 걸어주지 않는 것이 좋습니다.


3. 인덱스는 하나만 탑니다.
오라클등에서는 인덱스를 여러개 걸어주면 그것을 다 타지만 mysql에서는 인덱스를 하나밖에 타지 않습니다.
가령 Table_Name 에서 A필드와 B필드, C필드에 인덱스를 걸어주고, 아래와 같은 쿼리문을 날립니다.
select * from Table_Name where A='a' and B='b' and C='c';
이럴경우 세개의 인덱스중 하나의 인덱스만 탑니다.


4. 결합인덱스 사용법.
특정 테이블에서 동일한 쿼리문을 주로 사용하고 그 쿼리문이 아래와 같을 경우...
select * from Table_Name where A='a' and B='b' and C='c';
이경우 이 세개의 인덱스를 전부 타기 위해서는 결합인덱스를 걸어줘야 됩니다.
ALTER TABLE Table_Name ADD INDEX (A,B,C);
이렇게 인덱스를 줄 경우에 세개의 필드를 정렬해서 하나의 인덱스를 생성하기 때문에 해당인덱스를 탈 수 있습니다.


5. order by 에서 사용하는 인덱스.
select * from Table_Name order by A;
-> 이경우에 A인덱스를 탑니다.
select * from Table_Name where B='b' order by A;
-> 이경우 B인덱스만 탑니다.
이경우에 두개의 인덱스를 다 타게 하려면 결합인덱스로 (A,B)를 생성시키고, A의 조건을 where 문에 지정을 해줍니다.(이부분은 사실 저도 조금 헷갈리는 부분입니다. 어쨌든 며칠동안 인덱스를 살펴본 결과 이렇게 해줘야 될거 같아서 일단 적습니다. ㅠ.ㅠ)


6. 검색에서 사용하는 인덱스.
보통 본문검색을 할 때 [where A like '%a%' ]와 같은 방식으로 조건을 주는데, 이경우 인덱스를 타지 않습니다. 가끔보면 검색에 주로 사용되는 필드에 인덱스를 거는 경우를 볼 수 있는데, 쓸데없는 짓입니다.

단, [where A like 'a%']와 같이 검색을 하는 경우에는 인덱스를 탑니다.




MySQL 최적화 설계 (2006년)

MySQL 최적화 설계


MySQL을 위한 하드웨어 최적화

큰 테이블(2G가 넘는)이 필요하다면, 알파나 스팍 또는 IA64 등의 64bit 하드웨어를 고려해 보는 게 좋다. MySQL은 내부적으로 64bit 정수를 많이 사용하고 있으므로, 64bit CPU를 사용하면 좀더 나은 퍼포먼스를 기대할 수 있다.
거대한 데이터베이스를 위한 최적화는 보통 램, 빠른 디스크, CPU 순으로 진행된다.
더 많은 램은 사용되는 대부분의 key 페이지들을 램에 보관함으로써 빠른 key 갱신을 가능하게 한다.
안전한 트랜잭션을 사용하지 않거나 큰 디스크를 사용하고 파일 검사를 오랫동안 하는 일을 피하고 싶다면 UPS를 사용하여 전원 오류가 발생한 경우에도 시스템을 안전하게 종료시킬 수 있도록 하는 것도 좋은 생각이다.
하나의 전용 데이터베이스 서버를 가진 시스템이라면 1G 이더넷을 고려해 볼 필요가 있다. 네트워크 지연은 처리능력만큼 중요하다.(Latency is as important as throughput.)


디스크 최적화

시스템, 프로그램, 임시 파일들을 위한 전용 디스크를 갖춰라. (내용이) 자주 변경되는 경우라면 갱신 기록과 트랜잭션 기록 파일을 별도의 디스크에 배치한다.
데이터베이스 디스크에 있어서는 빠른 탐색 시간(seek time)이 요건이다. 큰 테이블에서 하나의 레코드를 찾기 위해 소요되는 탐색 횟수는 다음과 같이 추정해 볼 수 있다.
log(row_count) / log(index_block_length/3*2/(key_length + data_ptr_length))+1
예를 들어, 500,000개의 레코드를 가지고 있고 medium int 형 필드로 인덱싱하고 있는 테이블의 경우라면 log(500000) / log(1024/3*2/(3+4))+1 = 4 번의 탐색이 필요하다. 여기서 인덱스는 500,000 * 7 * 3/2 = 5.2M 정도의 크기가 될 것이다. 실제로는 대부분의 블록들이 버퍼에 저장되므로 아마도 1~2번 정도의 탐색이 필요하게 된다.
쓰기의 경우 새로운 키를 넣을 위치를 찾기 위해 위에서처럼 4번의 탐색이 필요하지만, 통상적으로 인덱스를 갱신하기 위해 2번의 탐색이 더 필요하다.

매우 큰 데이터베이스에 경우, 디스크 탐색 속도에의해 성능이 좌우되는데, 탐색 수는 더 많은 데이터를 얻을 때마다 N log N 씩 증가한다.
데이터베이스들과 테이블들을 다른 디스크들에 분할해 넣어라. MySQL에서는 이를 위해 심볼릭 링크를 사용할 수 있다.
Striping disks(RAID 0와 같은)는 읽기와 쓰기 양면에서 처리능력을 증가시킨다.
미러링을 동반하는 Striping disk(RAID 0+1)는 읽기/쓰기 성능을 향상시키고 안전성을 제공한다. 쓰기는 약간 느리다.
임시파일 또는 쉽게 갱신될 수도 있는 데이터에 대해서 미러링이나 RAID(RAID 0는 예외)를 사용하지 않는다.

Linux를 사용한다면 부팅할 때 hdparm -m16 -d1 명령을 디스크에 적용하여 다중 섹터 읽기/쓰기와 DMA 사용이 가능하도록 한다. 이는 반응 시간을 5~50%까지 증가시킨다.
Linux를 사용한다면 디스크를 마운트할 때 async(기본값이다)와 noatime 옵션을 부여하여 마운트한다.
일부 특정 응용프로그램의 경우 아주 특수한 테이블을 램디스크에 저장하는 것도 한 방법이 된다. 그러나 보통은 필요 없다.


운영체제 최적화

스왑을 제거한다. 메모리 문제가 있다면 시스템이 적은 메모리를 사용하도록 설정하기 보다는 메모리를 증설하는 것이 좋다.
데이터에 대해서 NFS 디스크를 사용하지 않는다. (NFS locking 문제에 봉착할 수 있다.)

시스템과 SQL 서버를 위해 open file 한계 수치를 증가시킨다. (safe_mysql 스크립트에 ulimit -n #을 추가한다.)
프로세스와 쓰레드의 개수 제한을 늘려준다.
상대적으로 큰 테이블을 사용할 일이 드물다면, 파일시스템이 파일을 여러 실린더에 분산시켜 저장하지 않도록 설정한다.(솔라리스)
큰 파일을 지원하는 파일시스템을 사용한다.(솔라리스)
어떤 파일시스템을 사용하는 것이 좋을지 선택한다. 리눅스의 Reiserfs 는 파일 열기, 읽기, 쓰기에 있어서 (ext2보다) 빠르다. 파일 검사도 단지 수 초 밖에 안 걸린다.


API 선택

PERL
OS 와 데이터베이스들간의 이식성 우수하다.
빠른 프로토타이핑에 적합하다.
DBI/DBD 인터페이스를 사용하는 것도 한 방법이다.

PHP
PERL 보다 익히기 쉬운 언어다.
PERL 보다 자원을 적게 사용. 때문에 웹서버에 내장시키기에 좋다.
PHP4로 업그레이드하여 더 나은 속도를 얻는 것도 한 방편이다.

C
MySQL 본래의 인터페이스이다.
더 빠르고 더 많은 제어가 가능하다.
저 수준. 때문에 (프로그래머가) 더 많은 일을 해야 한다.

C++
고 수준. 코딩에 더 많은 시간이 필요하다.
(MySQL C++ API는) 여전히 개발 단계에 있다.

ODBC
윈도우즈와 유닉스에서 동작한다.
거의 대부분의 다른 SQL 서버로 이식 가능하다.
느리다. MyODBC는 단순한 pass-through 드라이버이지만 본연의 인터페이스에 비해 19% 정도 느리다.
같은 일을 수행하는 많은 다른 도구들이 있다. 작업을 어렵게 하는 한 가지는 많은 ODBC 드라이버들이 제각기 다른 부분에서 상이한 버그들을 가지고 있다는 점이다.
문제 발생 소지가 많다. 마이크로소프트는 정기적으로 인터페이스를 변경한다.
미래가 불확실하다.(마이크로소프트는 ODBC보다 OLE 쪽에 더 많은 비중을 두고 있다.)

JDBC
이론적으로 OS, 데이터베이스 간의 이식성이 우수하다.
(브라우저와 같은)웹 클라이언트 상에서 동작할 수 있다.

Python + others
좋을 것이다. 그러나 우리는 사용하지 않는다.


응용프로그램 최적화

우선은 문제 해결에 집중하는 것이 필요하다.
응용프로그램을 제작할 때 다음 중 무엇이 가장 중요한지를 결정하는 것이 필요하다:

속도
OS 간의 이식성, SQL 서버들 간의 이식성, persistent connection을 사용한다.

응용프로그램 측의 캐싱은 SQL 서버의 부하를 감소시킨다.
응용프로그램 상에서 쓰이지 않는 컬럼은 쿼리하지 않는다.
SELECT * FROM table_name... 과 같은 쿼리를 사용하지 않는다.

응용프로그램의 모든 부분에 대하여 벤치마킹을 시도한다. 그러나 대부분의 노력을 부하의 가장 유력한 요인일 것 같은 부분의 응용프로그램들에 집중하는 것이 좋다. 이를 모듈 단위로 수행하면 발견한 병목구간을 빠른 '더미 모듈'로 대체하고 나서 다음 병목구간을 찾는 일로 넘어가는 식으로 일을 진행할 수 있다.

일련 작업 중에 많은 변경이 이루어진다면 LOCK TABLES을 이용한다. 예를 들면, 여러 개의 UPDATE 또는 DELETES 문장을 집합적으로 수행하는 경우 등.

이식성이 중요한 응용프로그램이라면
Perl DBI/DBD, ODBC, JDBC, Python (또는 범용 SQL 인터페이스를 가진 다른 언어들) 등을 사용한다.
모든 대상 SQL 서버들이 갖추고 있는, 또는 쉽게 다른 구문으로 모사할 수 있는 SQL 구문만 사용한다.
www.mysql.com 의 crash-me 페이지를 보면 도움이 될 것이다.
다른 OS나 SQL서버들에 없는 기능들을 제공하기 위해 wrapper 프로그램을 제작하여 사용한다.

보다 빠른 속도가 요구된다면
병목구간(bottleneck)을 (CPU, 디스크, 메모리, SQL 서버, OS, API, 또는 응용프로그램에서) 찾아내서 제거하는 일에 집중한다.
더 빠른 속도와 유연성을 제공하는 MySQL의 확장기능을 사용한다.
SQL 서버에 관한 지식을 더 많이 습득하여 문제를 해결하기 위한 가장 빠른 SQL 구문을 사용하고 병목요소를 사전에 제거한다.

테이블 레이아웃과 쿼리들을 최적화한다.
select 속도를 증가시키기 위해 replication을 사용한다.

데이터베이스가 느린 네트워크로 연결되어 있다면, 압축된 클라이언트/서버 프로토콜을 사용한다.

응용프로그램의 초기 버전이 이식성에 있어서 부실하더라도 걱정할 필요 없다. 문제를 먼저 해결하고 나서 나중에 언제든지 최적화할 수 있다.(Don't be afraid to make the first version of your application not perfectly portable; when you have solved your problem, you can always optimize it later.)


MySQL 최적화

컴파일러와 컴파일 옵션을 충분히 고려하여 선택한다.

가장 훌륭한 MySQL 시작 옵션을 찾는다.
MySQL 매뉴얼을 찾아보고 Paul DuBois 의 MySQL 서적을 읽는다.
EXPLAIN SELECT, SHOW VARIABLES, SHOW STATUS, SHOW PROCESSLIST 명령을 사용한다.
쿼리 옵티마이저가 동작하는 방식을 공부해 둔다.
테이블을 관리한다.(myisamchk, CHECK TABLE, OPTIMIZE TABLE)
MySQL 확장기능을 사용하여 속도를 증진시킨다.
특정 함수가 많은 곳에서 자주 사용될 것이라면 MySQL 사용자 정의 함수(UDF)로 직접 제작한다.
정말 필요한 경우가 아니라면, 테이블 수준 또는 컬럼 수준에서 GRANT 를 사용하지 않는다.
MySQL 고객 지원 서비스에 비용을 지불하고 문제 해결을 위한 도움을 받는다 :)


MySQL의 컴파일 및 설치

자신의 시스템에서 사용 가능한 최상의 컴파일러를 선택함으로 보통 10~30% 정도 성능 향상을 기대할 수 있다.
Intel 기반의 리눅스 시스템이라면 MySQL을 pgcc(펜티엄급에 최적화된 버전의 gcc)로 컴파일 한다. 그러나, (컴파일된) 바이너리는 인텔 펜티엄 CPU에서만 동장할 것이다.
MySQL 매뉴얼에서 권하는 플랫폼 별 최적화 옵션을 사용한다.

통상적으로 특정 CPU를 위한 본연의 컴파일러(Sparc을 위한 Sun Workshop과 같은)를 사용하면 gcc 보다 더 나은 성능을 기대할 수 있다. 그러나, 항상 그런 것은 아니다.
MySQL을 사용하려는 한 가지 문자셋만 지정하여 컴파일한다.

mysqld 실행파일을 정적으로 컴파일(--with-mysqld-ldflags=-all-static)하고 strip sql/mysqld 명령으로 최종 실행파일에서 디버그 코드를 제거한다.
MySQL이 C++ 예외처리를 하지 않으면, 즉 예외처리 지원 옵션을 빼고 컴파일하면 성능이 크게 향상된다.

운영체제가 네이티브 쓰레드(native thread)를 지원한다면 mit-pthreads 라이브러리 대신 네이티브 쓰레드를 사용하도록 한다.
생성된 실행파일을 MySQL 벤치마크 테스트로 테스트해 본다.


유지 보수

가능하면 정기적으로 OPTIMIZE table 을 실행한다. 이는 특히 자주 갱신되는 가변크기 레코드들에 대해 중요하다.
정기적으로 myisamchk -a 명령을 사용하여 테이블들의 key 분산 상태를 갱신한다. 이 작업을 수행하기 전에 반드시 MySQL을 셧다운해야 한다는 점을 잊지 않는다.

파일들이 조각난 상태라면 다른 디스크로 모두 복사하고 기존의 디스크를 깨끗이 한 후 다시 파일을 옮기는 일도 시도해 볼만한 가치가 있다.

문제가 발생한다면, 테이블을 myisamchk나 CHECK table 명령으로 검사한다.
MySQL의 상태를 mysqladmin -i10 processlist extended-status 명령으로 모니터한다.
MySQL GUI 클라이언트를 사용하면 프로세스 목록과 상태를 다른 윈도우에서 모니터할 수 있다.
mysqladmin debug 명령을 사용해서 잠금(lock)과 성능에 관한 정보를 얻는다.


SQL 최적화

사용하는 것이 좋은 것에만 SQL을 사용하고 그렇지 않은 곳에서는 다른 것을 사용한다. SQL는 다음과 같은 곳에 사용한다.

WHERE 절에 의존하여 행을 찾는 경우
테이블들을 JOIN 할 경우
GROUP BY
ORDER BY
DISTINCT

다음과 같은 일에는 사용하지 않는다.

데이터(date 와 같은)의 유효성을 검증하는 경우
계산기로 사용


Tips

key를 폭 넓게 사용한다.

key는 검색에는 좋지만, key 컬럼에 대해 insert 나 update를 수행하는 데는 좋지 않다.

데이터를 제3의 보통 데이터베이스 형식(in the 3rd normal database form)으로 유지하되, 속도를 중시한다면 정보의 중복이나 요약 테이블(summary tables)을 생성하는 일을 기피할 필요는 없다.

큰 테이블에 대해서 GROUP BY를 남용하는 대신 그 테이블에 대한 요약 테이블을 생성하고 이 테이블에 대해 쿼리하는 것이 낫다.

UPDATE table set count=count+1 where key_column=constant 와 같은 문장은 매우 빠르다!

기록 테이블(log tables)에 관한 한, 정기적으로 요약 테이블을 만드는 것이 요약테이블을 그대로 두는 것 보다 나을 것이다.

INSERT에서 디폴트 값(default values)의 잇점을 십분 활용한다.

중요한 MySQL 기동 옵션들
back_log 접속 수가 많다면 변경한다.
thread_cache_size 접속 수가 많다면 변경한다.
key_buffer_size 인덱스 페이지를 위한 풀(pool) 크기. 큰 수치를 지정하는 것도 가능하다.
bdb_cache_size BDB 테이블들에 의해 사용되는 레코드와 키 캐시 크기.
table_cache 많은 테이블을 가지고 있거나 동시 접속 수가 많다면 변경한다.
delay_key_write 모든 키 쓰기 동작을 버퍼링할 필요가 있다면 지정한다.
log_slow_queries 시간이 많이 걸리는 쿼리를 찾을 때 사용한다.
max_heap_table_size GROUP BY 절에서 사용된다.
sort_buffer ORDER BY 와 GROUP BY 절에서 사용된다.
myisam_sort_buffer_size REPAIR TABLE 문에서 사용된다.
join_buffer_size 키 없이 join 할 때 사용된다.

테이블 최적화

MySQL은 풍부한 상이한 컬럼 유형(type)들의 집합을 가지고 있다. 각 컬럼에 대해 가장 효과적인 유형을 선택하여 사용하는 것이 필요하다.

ANALYSE 프로시저는 테이블을 위한 최적의 컬럼 유형을 찾는데 도움이 될 것이다.
SELECT * FROM table_name PROCEDURE ANALYSE()

널 값을 저장하지 않을 컬럼은 NOT NULL 로 지정한다. 이는 특별히 인덱스 컬럼의 경우 중요하다.

ISAM 테이블들을 MyISAM 으로 변경한다.

가능하다면, 테이블을 고정된 테이블 형식으로 만드는 것이 좋다.

사용하지 않을 인덱스는 아예 만들지 않는다.

MySQL이 인덱스의 접두부(prefix)에 대해서 검색을 수행할 수 있다는 점을 활용한다.

INDEX (a, b) 로 되어 있다면, (a)에 대해 인덱싱할 필요는 없다.

길이가 긴 CHAR 형이나 VARCHAR 형이라면 해당 컬럼에 대해 인덱스를 생성하지 않고 그 컬럼의 접두부에 대해서만 인덱스를 생성하면 공간이 절약된다.
CREATE TABLE table_name (hostname CHAR(255) not null, index(hostname(10)))

각 테이블을 위한 가장 효과적인 테이블 유형을 사용한다.

서로 다른 테이블들 중 동일한 정보를 가지는 컬럼들은 같은 유형, 같은 이름을 가지도록 정의한다.


MySQL이 데이터를 저장하는 방식

데이터베이스는 디렉토리로 저장된다.

테이블은 파일로 저장된다.

컬럼은 가변 길이나 고정 길이 유형으로 파일 안에 저장된다. BDB 테이블에서 데이터는 페이지에 저장된다.

메모리 기반의 테이블도 지원된다.

데이터베이스와 테이블들은 다른 디스크로부터 심볼릭 링크될 수 있다.

Windows용 MySQL은 .sym 파일을 이용하여 데이터베이스에 대한 내부적인 심볼릭 링크를 지원한다.


MySQL 테이블 유형들
HEAP 테이블: 고정된 수의 레코드만 가지는 테이블로서 오직 메모리에만 저장되며 HASH 인덱스로 인덱스된다.

ISAM 테이블: MySQL 3.22에서 사용된 구식 B-tree 테이블 유형이다.

MyISAM 테이블: ISAM 테이블의 새 버전으로 많은 확장 기능들을 가지고 있다.
바이너리 호환성
NULL 컬럼에 대한 인덱싱
가변 크기 테이블의 파편화(fragmentation)가 ISAM 테이블 보다 적음
거대 파일 지원
인덱스 압축 향상
키 통계 향상
더 향상되고 빠른 auto_increment 지원
Sleepycat의 Berkeley DB(BDB) 테이블: 안전한 트랜잭션 지원(BEGIN WORK / COMMIT | ROLLBACK)


MySQL 레코드 유형(ISAM/MyISAM 테이블과 관련하여서만)
MySQL은 모든 컬럼들이 고정 크기 유형이라면 (VARCHAR, BLOB, TEXT 컬럼이 없다면) 테이블을 고정 크기 테이블로 생성한다. 그렇지 않다면, 가변 크기 유형의 테이블로 만든다.
고정 크기 유형은 동적 크기 유형에 비해 속도가 빠르며 안전하다.

동적 크기 레코드 유형은 대개 보다 적은 공간을 사용하지만 테이블의 갱신이 자주 발생한다면 파편화가 가중되기마련이다.

어떤 경우에는 주 테이블의 속도를 향상시키기 위해 모든 VARCHAR, BLOB, TEXT 컬럼들을 다른 테이블로 옮기는 것도 유용할 때가 있다.

myisampack(ISAM 테이블에서는 pack_isam)을 사용하면 읽기 전용, 압축된 테이블을 만들 수 있다.

느린 디스크를 사용할 때는 디스크 사용량을 최소화하는 것이 좋은 한 방법이 된다.
압축된 테이블은 더 이상 갱신되지 않는 로그 테이블 등에 사용하면 최상이다.


MySQL 캐시들 (한 번 적재되어 모든 쓰레드가 공유)
키 캐시: key_buffer_size, 기본값은 8M
테이블 캐시: table_cache, 기본값은 64
쓰레드 캐시: thread_cache_size, 기본값은 0
호스트명 캐시: 컴파일할 때 변경 가능, 기본값은 128
메모리에 맵핑된 테이블(Memory mapped tables): 현재는 압축된 테이블을 위해서만 사용된다.
MySQL은 행(raw) 캐시를 가지고 있지 않다. 그러나, 운영체제에게 이 일을 시킬 수 있다!


MySQL 버퍼 변수들 (공유되지 않으며 실행 중 적재됨)
sort_buffer: ORDER BY / GROUP BY 절에서
record_buffer: 테이블을 스캔할 때
join_buffer_size: 키 없이 join을 수행할 때
myisam_sort_buffer_size: REPAIR TABLE에서
net_buffer_length: SQL 문장을 읽을 때와 결과 값을 버퍼링할 때
tmp_table_size: 임시 결과값을 위한 HEAP-table-size

MySQL 테이블 캐시가 동작하는 방식
MyISAM 테이블의 열려 있는 각각의 인스턴스는 인덱스 파일과 데이터 파일을 사용한다. 만일 어떤 테이블이 두 개의 쓰레드에 의해 사용되거나 같은 쿼리에서 두 번 사용되면, MyISAM이 인덱스 파일은 공유하지만 데이터 파일은 또 하나의 인스턴스를 위해 추가로 열게 된다.

캐시 안의 모든 테이블이 사용 중이라면 그 캐시는 일시적으로 테이블 캐시 크기보다 커진다. 이러한 상황이 발생하면, 그 다음 방면된 테이블이 닫히게 된다.

mysqld 변수 Opend_tables를 검사해 보면 테이블 캐시가 너무 작은지 아닌지를 알 수 있다. 이 값이 높으면 테이블 캐시를 늘려줘야 한다!



MySQL 확장들 / 속도 증진 최적화


  • 최적화된 테이블 유형을 사용한다.(HEAP, MyISAM, BDB 테이블)
  • 데이터를 위한 최적의 컬럼을 사용한다.
  • 가능한 한 고정 크기 레코드를 사용한다.
  • 다른 잠금 유형(lock types)를 사용한다.(SELECT HIGH_PRIORITY, INSERT LOW_PRIORITY)
  • Auto_increment
  • REPLACE (REPLACE INTO table_name VALUES (...))
  • INSERT DELAYED
  • LOAD DATA INFILE / LOAD_FILE()
  • 한번에 많은 레코드를 추가하기 위해서는 다중 레코드 INSERT를 사용한다.
  • SELECT INTO OUTFILE
  • LEFT JOIN, STRAIGHT JOIN
  • IS NULL 과 접목된 LEFT JOIN 사용
  • 일부 경우, ORDER BY 는 키를 사용할 수 있다.
  • 하나의 인덱스에 있는 컬럼들만 쿼리할 경우에는 쿼리를 수행하기 위해 그 인덱스 트리만 사용하게 된다.
  • 조인은 보통 subselect 보다 빠르다. (대부분의 SQL 서버들에서 그러하다.)
  • LIMIT
    • SELECT * from table1 WHERE a > 10 LIMIT 10, 20
    • DELETE * from table1 WHERE a > 10 LIMIT 10
  • foo IN (상수 목록) 구문은 매우 최적화되어 있다.
  • GET_LOCK() / RELEASE_LOCK()
  • LOCK TABLES
  • INSERT 와 SELECT 는 동시에 실행 될 수 있다.
  • 작동하고 있는 서버로 읽어 들일 수 있는 UDF 함수들
  • 압축된 읽기 전용 테이블들
  • CREATE TEMPORARY TABLE
  • CREATE TABLE .. SELECT
  • MyISAM 테이블을 RAID와 사용하면 하나의 파일을 여러개의 파일들로 나누어 일부 파일시스템의 2G 제한을 넘어서는 것이 가능하다.
  • Delayed_keys
  • 리플리케이션(replication)



MySQL이 인덱스를 사용할 경우

>, >=, =, <, <=, 키에 대해 IF NULL 과 BETWEEN을 사용할 때
SELECT * FROM table_name WHERE key_part1=1 and key_part2 > 5;
SELECT * FROM table_name WHERE key_part1 IS NULL;
와일드카드 문자로 시작하지 않는 LIKE 절을 사용할 때
SELECT * FROM table_name WHERE key_part1 LIKE 'jani%'
조인을 수행하면서 다른 테이블들로부터 레코드를 가져올 때
SELECT * from t1, t2 where t1.col=t2.key_part;
특정 인덱스에 대해서 MAX() 나 MIN() 값을 구할 때
SELECT MIN(key_part2), MAX(key_part2) FROM table_name where key_part1=10;
키의 접두부에 대해 ORDER BY 나 GROUP BY 절을 수행할 때
SELECT * FROM foo ORDER BY key_part1, key_part2, key_part3;
쿼리에 사용되는 모든 컬럼이 한 개의 키의 부분(part)일 경우
SELECT key_part3 FROM table_name WHERE key_part1=1;

MySQL이 인덱스를 사용하지 않을 경우

MySQL은 테이블 전체를 스캔하는 더 빠를 것이라고 판단되면 인덱스를 사용하지 않는다. 예를 들어, key_part1이 1과 100사이의 값을 고르게 가지고 있다면, 다음과 같은 쿼리에서 인덱스를 사용하는 것은 좋지 않다.
SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90;
HEAP 테이블을 사용하고 있으며, 모든 키 부분들에 대해서 = 로 검색하지 않을 경우
HEAP 테이블에 대해 ORDER BY 절로 쿼리할 경우
맨 처음의 키 부분을 사용하지 않을 경우
SELECT * FROM table_name WHERE key_part2 = 1;
와일드카드 문자로 시작하는 LIKE 를 사용할 경우
SELECT * FROM table_name WHERE key_part1 LIKE '%jani%'
하나의 인덱스에 대해서 검색하면서 다른 인덱스에 대해서는 ORDER BY 를 적용할 때
SELECT * FROM table_name WHERE key_part1 = # ORDER BY key2;

EXPLAIN 사용법 익히기

지나치게 느리다고 생각되는 모든 쿼리 문장에 대해 EXPLAIN 을 사용한다.
mysql> explain select t3.DateOfAction, t1.TransactionID
-> from t1 join t2 join t3
-> where t2.ID = t1.TransactionID and t3.ID = t2.GroupID
-> order by t3.DateOfAction, t1.TransactionID;
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| t1 | ALL | NULL | NULL | NULL | NULL | 11 | Using temporary; Using filesort |
| t2 | ref | ID | ID | 4 | t1.TransactionID | 13 | |
| t3 | eq_ref | PRIMARY | PRIMARY | 4 | t2.GroupID | 1 | |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
유형 ALL과 범위는 잠재적인 문제점을 알리고 있다.


SHOW PROCESSLIST 사용법 익히기

현재 진행 상황을 파악하기 위해서는 SHOW processlist 를 사용한다.
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| 6 | monty | localhost | bp | Query | 15 | Sending data | select * from station,station as s1 |
| 8 | monty | localhost | | Query | 0 | | show processlist |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
mysql에서 KILL을 사용하거나 명령행에서 mysqladmin을 사용하여 불필요한(runaway) 쓰레드들을 없앨 수 있다.


MySQL이 쿼리를 해결하는 방법을 찾는 방법

다음 명령들을 실행해서 결과를 이해하도록 노력한다.
  • SHOW VARIABLES;
  • SHOW COLUMNS FROM ... \G
  • EXPLAIN SELECT ... \G
  • FLUSH STATUS;
  • SELECT ...;
  • SHOW STATUS;
MySQL은 이런 경우 극히 우수하다

  • 로그 기록시
  • 많은 연결이 이루어 질 때, 연결 속도가 매우 빠르다.
  • SELECT 와 INSERT 를 동시에 사용하는 곳에서.
  • update를 시간이 오래 걸리는 select 문과 결합하지 않을 때
  • 대부분의 select/update 문이 고유한 키들을 사용할 때
  • 많은 테이블을 장시간 잠금(lock) 충돌 없이 사용할 때
  • 크기가 큰 테이블을 가지고 있을 때 (MySQL 은 매우 컴팩트한 테이블 포맷을 사용한다.)

MySQL 사용에 있어서 피해야 할 것들


  • 테이블을 UPDATE 또는 삭제된 행을 테이블에 대해 INSERT하면서 시간이 오래 걸리는 SELECT 절들과 결합시키는 일
  • WHERE 절에 올 수 있는 것들에 대한 HAVING
  • 키를 사용하지 않은, 또는 충분히 유니크하지 않은 키를 사용한 JOIN
  • 컬럼 유형이 서로 다른 컬럼들에 대해 JOIN 수행
  • 온전한 키 전체가 아닌 키의 부분에 대해서만 '=' 로 비교연산할 때 HEAP 테이블을 사용



MySQL monitor 에서 UPDATE 나 DELETE를 사용하면서 WHERE 절을 생략하는 일. 만약 자신이 이런 경향이 있다면, mysql 클라이언트 프로그램을 실행할 때 --i-am-a-dummy 옵션을 추가하기 바란다.


MySQL의 독특한 잠금들(locks)

  • 내장된 테이블 잠금
  • LOCK TABLES (모든 테이블 유형에 대해 동작함)
  • GET_LOCK() / RELEASE_LOCK()
  • Page locks (BDB 테이블에 대해서)
  • ALTER TABLE 역시 BDB 테이블에 대해 테이블 잠금을 수행함
  • LOCK TABLES 는 다중 읽기 작업 또는 한개의 쓰기 작업을 허용한다.
  • 보통 WRITE 잠금은 READ 잠금 보다 우선 순위가 높다. 쓰기 작업이 무한정 대기 상태에 놓이게 되는 경우를 피하기 위해서다(to avoid starving the writers). 그리 중요하지 않은 쓰기 작업은 LOW_PRIORITY 키워드를 사용하여 lock handler가 읽기 작업에 먼저 허가를 내어 주도록 하는 것도 한 방법이다.
    • UPDATE LOW_PRIORITY SET value=10 WHERE id=10;

문제를 쉽게 해결하기 위해 MySQL로부터 더 많은 정보를 얻는 기법들
  • MySQL 만의 기능들을 항상 주석처리함으로써 쿼리의 이식성 높일 수 있다.
    • SELECT /*! SQL_BUFFER_RESULTS */ ...
    • SELECT SQL_BUFFER_RESULTS ...
  • MySQL이 임시 결과 세트를 만들도록 강제한다. 임시 세트가 만들어지면, 그 테이블들에 대한 모든 잠금이 해제된다. 이는 테이블 잠금으로 인해 문제가 발생했을 때나 쿼리 결과를 클라이언트로 전송하는데 오랜 시간이 소요되는 경우에 도움이 된다.
    • SELECT SQL_SMAIL_RESULT ... GROUP BY ...
  • 결과 세트가 적은 수의 레코드만 가지게끔 하도록 옵티마이저에게 지시한다.
    • SELECT SQL_BIG_RESULT ... GROUP BY ...
  • 결과 세트가 많은 수의 레코드를 가지도록 옵티마이저에게 지시한다.
    • SELECT STRAIGHT_JOIN ...
  • 옵티마이저가 FROM 절에 나타난 순서대로 테이블을 join 하도록 강제한다.
    • SELECT ... FROM table_name [USE INDEX (index_list) | IGNORE INDEX (index_list)] table_name2
  • MySQL이 특정 인덱스들을 사용하거나 무시하도록 강제한다.



트랜잭션 사용예

MyISAM 테이블에 대해 트랜잭션을 수행하는 방법:
mysql> LOCK TABLES trans READ, customer WRITE;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement where customer_id=some_id;
mysql> UNLOCK TABLES;
Berkeley DB 테이블에 대해 트랜잭션을 수행하는 방법:
mysql> BEGIN WORK;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement where customer_id=some_id;
mysql> COMMIT;

다음과 같이 함으로써 여러 트랜잭션들 간의 간섭을 방지할 수 있다는 점에 주목할 필요가 있다:
UPDATE customer SET value=value+new_value WHERE customer_id=some_id;


REPLACE 사용예
REPLACE는 테이블의 이전 레코드가 새 레코드와 같은 고유 인덱스 값을 가지고 있다면 예전 레코드가 먼저 삭제되고 새 레코드가 추가된다는 점만 제외하면 INSERT와 똑같이 작동한다.

다음과 같이 하는 대신,
SELECT 1 FROM t1 WHERE key=#
IF found-row
LOCK TABLES t1
DELETE FROM t1 WHERE key1=#
INSERT INTO t1 VALUES (...)
UNLOCK TABLES t1;
ENDIF
다음과 같이 한다.
REPLACE INTO t1 VALUES (...)


일반적인 팁
프라이머리 키는 짧은 것을 사용한다. 테이블 조인할 때는 문자열형 보다는 숫치형을 사용한다.

여러 부분으로 구성된 키를 사용할 때는 첫 번째 부분이 가장 많이 사용되는 키이어야 한다.
의심스러울 때는, 앞부분이 더 많이 중복된 컬럼을 사용해서 보다 나은 키 압축 효과를 얻는다.

클라이언트를 실행 중이고 MySQL 서버가 같은 머신에 있다면, TCP/IP 대신에 유닉스 소켓을 사용하여 서버에 연결하는 것이 좋다.(이렇게 하면 7.5% 정도까지 효율이 증진된다.)

MySQL 서버에 접속할 때 호스트이름이나 localhost를 지정하지 않으면 유닉스 소켓으로 접속하게 된다. 가능하다면 --skip-locking(일부 운영체제에서는 이 것이 기본값이다)을 사용한다. 이는 외부적인 잠금을 사용하지 않게 되고 퍼포먼스가 향상된다.

긴 키를 사용하기 보다는 응용프로그램 수준에서 해시된 값을 사용한다.
SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND col_1='constant' AND col_2='constant';

Store BLOB's that you need to access as files in files. 데이터베이스에는 파일이름만 저장한다.

레코드들의 큰 부분을 지우는 것 보다 레코드 전체를 지우는 것이 더 빠르다.

SQL이 충분히 빠르지 않다면, 데이터에 접근하는 더 낮은 수준의 인터페이스를 점검해 본다.


MySQL 3.23을 사용할 때 얻을 수 있는 이점


  • MyISAM; 이식이 수월한 거대 테이블 유형
  • HEAP; 메모리 상의 테이블
  • Berkeley DB; Sleepycat에서 제공하는 트랙잰션이 가능한 테이블
  • 대폭 확대된(풀린) 제한들
  • 동적 문자셋
  • 더 많이 제공되는 STATUS 변수들
  • CHECK table, REPAIR table
  • 더 빠른 GROUP BY 절과 DISTINCT 절
  • 최적화된 LEFT JOIN ... IF NULL
  • CREATE TABLE ... SELECT
  • CREATE TEMPORARY table_name (...)
  • 임시적인 HEAP에서 MyISAM 테이블로의 자동 변환
  • 리플리케이션
  • mysqlhotcopy 스크립트



실제 작업에서 중요한 기능들

  • 진보된 트랜잭션
  • 오류로부터 안전한 리플리케이션
  • 텍스트 검색
  • 많은 테이블의 삭제 (이 작업 후에 많은 테이블의 갱신이 이루어진다.)
  • 너 나은 키 캐시
  • 원자화된 RENAME (RENAME TABLE foo as foo_old, foo_new as foo)
  • 쿼리 캐시
  • MERGE TABLES
  • 향상된 GUI 클라이언트





DB관련 기타 정보들 (2006년 ~ 2009년)

(네이버블로그에서 가져온 과거 펌질)

*Mysql - ErrorCode / ErrorNo (2009년)
http://www.supersky.pe.kr/index.php?pl=74&ct1=2&ct2=3


*MySQL에 대용량 데이터 import하기 (2009년)
http://toracle.egloos.com/1533467


*초보도 알아야할 MySQL 튜닝 18가지 (2009년)
http://leopit.com/Leophp/board/lecture_board/view.php?id=46&board_mode=mysql


*Using MySQL Full-text Searching
http://devzone.zend.com/26/using-mysql-full-text-searching/


*MySQL : Full-Text Search Functions
http://dev.mysql.com/doc/refman/5.6/en/fulltext-search.html


*MySQL 데이터베이스 서버 5.0의 신기능
http://rhio.tistory.com/13


Index rebuild에 관련된 잘못된 미신?
http://database.sarang.net/?inc=read&aid=20246&criteria=oracle&subcrit=&id=&limit=20&keyword=%B9%CC%BD%C5&page=1

MySQL '/tmp/mysql.sock' 에러 복구방법

(네이버블로그에서 옮겨옴)

'/tmp/mysql.sock' 에러 복구방법

2006/11/30 17:18 http://blog.naver.com/jujac/20031096672

./mysql 실행시
"tmp/mysql.sock" 에러가 발생하면
/usr/local/mysql/bin 에서 아래 1과 2를 차례대로 실행
1. ./mysqld_safe --user=root &
2. ./mysqld_safe &
(1번만 해줘도 보통 되드만;;)


(추가)----------------------------------------------------------------
물론, 기 가동중인 MySQL은 종료를 해주는게..^^
[http://blog.naver.com/jujac/20031505514 참조]

/usr/local/mysql/bin/mysqladmin -u root -p shutdown
또는
/etc/init.d/mysqld stop


덧글
하하 2007/03/18 14:07
좋은정보 감사합니다~~

MySQL 백업및 복구

(네이버블로그에서 옮겨옴)

MySQL 백업및 복구 (Backup & Restore)

2006/10/25 18:59 http://blog.naver.com/jujac/20029740386

1. mysql 덤프하기 (백업)
mysqldump -u[사용자아이디] -p 데이터베이스명 [테이블명] > 저장될 파일명
ex)
mysqldump -u userid -p mydatabase > _backup.sql
mysqldump -u userid -p mydatabase member_table > _backup.sql

2. mysql restore (복구)
mysql -u[사용자아이디] -p [디비명] < 덤프파일명
ex)
mysql -u userid -p mydatabase < _backup.sql

cf. 상이한 Charset간의 데이터 이전
먼저, 해당 덤프파일의 BOM 및 문서 charset을 원하는 형태로 변경
mysql -u[사용자아이디] --default-character-set=[charset-name] -p [디비명] < 덤프파일명
ex)
[ euc-kr 에서 utf-8 으로 변경하여 백업복구를 실행할 경우 ]
mysql -u userid -p --default-character-set=utf8 mydatabase < _backup.sql
※ 이외의 여러가지 응용방법에 대하여서는 MySQL 본사홈페이지의 메뉴얼을 참고

MySQL의 데이터 타입정보

(네이버블로그에서 옮겨옴)

2006/09/24 20:44 http://blog.naver.com/jujac/20028719280

MySQL의 데이터 타입정보
-----------------------------------------------------------
TINYINT (-128 ~ 127)
SMALLINT (-32768 ~ 32767)
MEDIUMINT (-8388608 ~ 8388607)
INT (-2147483648 ~ 2147483647)
BIGINT (-9223372036854775808 ~ 9223372036854775807)
FLOAT
DOUBLE
DECIMAL(NUMERIC)
DATE (1000-01-01 ~ 9999-12-31, YYYY-MM-DD)
DATETIME (1000-01-01 00:00:00 ~ 9999-12-31 23:59:59, YYYY-MM-DD HH:MM:SS)
TIMESTAMP (1970-01-01 00:00:00 ~ 2106..., YYYYMMDD[HH[MM[SS]]]) O
TIME (-838:59:59 ~ 838:59:59, HH:MM:SS)
YEAR (1901 ~ 2155, 0000, YYYY)
CHAR (1~255) 고정길이
VARCHAR (1~255) 가변길이
TINYTEXT (0 ~ 255)
TEXT (0 ~ 65535)
MEDIUMTEXT (0 ~ 16777215)
LONGTEXT (0 ~ 4294967295)
TINYBLOB (0 ~ 255)
BLOB (0 ~ 65535)
MEDIUMBLOB (0 ~ 16777215)
LONGBLOB (0 ~ 4294967295)

MySQL 4.1.12에서의 Illegal mix of collations Error

(네이버블로그에서 옮겨옴)

[SQL] MySQL 4.1.12에서의 Illegal mix of collations Error

2006/02/07 13:31 http://blog.naver.com/jujac/20021380449

MySQL 4.1.12 상에서 EUC-KR과 UTF-8을 동시에 써야하는 문제가 발생했다.
기존 버전은 EUC-KR기반이었고.. 신 버전은 다국어지원 문제로 UTF-8을 사용하였기에
업그레이드를 위해 기존 버전과 신버전이 동시에 공존하여야 하는 문제가 발생한 것..
DB나 Table이야 각각의 charset에 맞게 설정하면 그만이지만..
Connection은 일단 UTF-8이나 EUC-KR 둘 중에 하나를 선택하여야 한다.

1. 일단, 기존버전을 유지한 상태에서 DB를 copy떠서 charset만 변경시켰다.
  원본DB: db_1 → 사본DB: db_2

2. 그리고.. 신버전의 UTF-8의 사용을 위해 DB연결을 시도하였더니 다음과 같은 에러 발견.
  Illegal mix of collations (euckr_korean_ci, IMPLICIT) and
  (latin1_swedish_ci, COERCIBLE) ...

3. 따라서 Connection을 일치 시켜야만 했다.
그런이유로.. 다음과 같은 파일을 작성하여 include하였다.

<?
$query = 'set session character_set_connection=utf8;';
mysql_query($query) or die("[#".__LINE__."]".mysql_error());
$query = 'set session character_set_client=utf8;';
mysql_query($query) or die("[#".__LINE__."]".mysql_error());
$query = 'set session character_set_results=utf8;';
mysql_query($query) or die("[#".__LINE__."]".mysql_error());
$query = 'set collation_connection=utf8_unicode_ci;';
mysql_query($query) or die("[#".__LINE__."]".mysql_error());
?>

4. 이후 작성되는 모든 mysql관련 명령어는 UTF-8 의 적용을 받는다.


덧글
멋진녀석 2008/09/10 14:24
감사합니다 담아갈께요
미개 2008/09/25 13:17
담아갈께요.
포데스 2010/03/08 17:35
감사. 담아가요.
개구장이 2011/01/19 18:38
감사합니다~
arkim04233 2011/08/03 15:52
감사합ㄴㅣ다

Window에서 Oracle Client 설치 및 기동


(네이버블로그에서 옮겨옴 - 2005년도 상황이기에 다를 수 있음)

[Oracle] Window에서 Oracle Client 설치 및 기동

2005/08/18 18:52 http://blog.naver.com/jujac/20015983467

Window에서 Oracle Client 설치 및 기동


Step 1: Download the appropriate Instant Client packages for your platform. All installations REQUIRE the Basic package.
해당 플렛폼에 맞추어 Client를 다운받는다.

http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html


Step 2: Unzip the packages into a single directory such as "instantclient".
다운받은 zip파일의 압축을 푼다.

(폴더명 이하: C:\WINDOWS\SYSTEM32\DRIVER\instantclient)


Step 3: Set the library loading path in your environment to the directory in Step 2 ("instantclient"). On many UNIX platforms, LD_LIBRARY_PATH is the appropriate environment variable. On Windows, PATH should be used.
시스템 환경변수를 설정하여준다.

기본 PATH에 추가: C:\WINDOWS\SYSTEM32\DRIVER\instantclient

환경변수 "TNS_ADMIN" 추가: C:\WINDOWS\system32\drivers\instantclient\

(TNS_ADMIN의 값은 Step4의 TNSNAMES.ORA파일의 위치를 지정한다.)


Step 4: TNSNAMES.ORA
환경변수 "TNS_ADMIN"에 지정한 폴더에 TNSNAMES.ORA파일을 생성한다.

파일내용===========================================
{tns-name} =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = {Oracle-server IP})(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = {schema-name})
)
)
===================================================


Step 5: ODBC config.
ODBC설정에서 사용자DNS를 추가한다.
추가 > Microsoft ODBC for oracle
데이터원본이름: 맘대로
설명: 맘대로
사용자이름: 접속아이디
서버: Oracle server IP


Step 6: Start your application and enjoy.
TOAD or SQL*PLUS를 사용한다.

뭐.. 다운로드는 각자 알아서.. 유료프로그램을 어쩌라거~ ㅡㅡ;;


덧글
왕구라 2005/11/09 09:41
감사
주작 2005/11/09 12:07
깜짝이야.. 아디땜시 놀랬어요~ 왕구라 라기에..ㅋㅋ
멍이 2006/08/21 13:16
담아갑니당 (__)
피떵거리 2007/04/30 11:12
담아갑니다..
나다 2007/04/30 16:35
담아갑니다.

Oracle 에러 메세지 정리 (2005년)

(네이버블로그에서 옮겨옴)

[Oracle] 에러 메세지 정리

2005/08/18 18:52 http://blog.naver.com/jujac/20015983436

에러코드일반: http://blog.naver.com/nukiboy/40006002763
ORA-00000 to ORA-00899: http://blog.naver.com/hanmongs/60006461448
ORA-00900 to ORA-01499: http://blog.naver.com/hanmongs/60006462287
ORA-01500 to ORA-02099: http://blog.naver.com/hanmongs/60006462330
ORA-02100 to ORA-04099: http://blog.naver.com/hanmongs/60006462356
ORA-04100 to ORA-07499: http://blog.naver.com/hanmongs/60006462437
ORA-07500 to ORA-09857: http://blog.naver.com/hanmongs/60006462464
ORA-09858 to ORA-12299: http://blog.naver.com/hanmongs/60006462569
ORA-12300 to ORA-12399: http://blog.naver.com/hanmongs/60006462587
ORA-12400 to ORA-12699: http://blog.naver.com/hanmongs/60006462608
ORA-12700 to ORA-19399: http://blog.naver.com/hanmongs/60006462636
ORA-19400 to ORA-24279: http://blog.naver.com/hanmongs/60006462656
ORA-24280 to ORA-29249: http://blog.naver.com/hanmongs/60006462675
ORA-29250 to ORA-32799: http://blog.naver.com/hanmongs/60006462698
ORA-32800 to ORA-32999: http://blog.naver.com/hanmongs/60006462721
ORA-33000 to ORA-65535: http://blog.naver.com/hanmongs/60006462742



MySQL 4.1.1 이전 버전에서 UTF-8 데이터 저장불가

(네이버블로그에서 옮겨옴)


MySQL에서 UTF-8데이터 저장하기

2005/08/18 18:33 http://blog.naver.com/jujac/20015982731

쪽팔리지만..
PHP와 MySQL의 연동시에 새삼 알게된게 있다. ㅡㅡ;;
몇년이나 해왔던 녀석들인데.. 이제사 알게되는것도 있다니..
내 지식의 한계를 통감할 뿐이다.. ㅠㅠ
문제는..
유니코드의 MySQL저장.. 이것에서 문제가 생겨 한참을 고민하던 중..
MySQL 4.1.1 이상 버전에서만 UTF-8이 지원된다는 것을 알게됬다.
(물론, compile시 ./configure --with-charset=utf-8 은 기본이고.. ㅡㅡ;;)
MySQL 4.0.3 에서 삽질 한참했다.. ㅠoㅠ)>
---------------------------------------------------------------------------
출처: http://www.mysql.com
미나상.. 나와 같은 실수를 반복하지 않기를..
129 ·