기본키 또는 Primary Key라고 부르는 이 값의 정체는?

 

DB에서 테이블을 생성할 때 하나 또는 그 이상의 항목을 기본키(Primary Key)로 설정할 수 있습니다.

기본키는 해당 테이블에서 가장 기본적인 값을 가집니다.

이를 PostgreSQL에서 몇 가지 측면에서 뜯어보면 다음과 같습니다.

 

1. 기술적인 의미

 - 기본키는 다른 항목과 절대로 중복되어 나타날 수 없는 단일 값(unique)을 가집니다.

 - 기본키는 절대 null(아무런 값이 없는 상태) 값을 가질 수 없습니다.

 ex) 예를 들면 주민등록번호 같은 개념이죠. 동일한 이름을 가진 사람은 많을 수 있고,
      동일한 날에 동일한 이름을 가진 사람도 존재할 수 있지만, 결국 그 사람들이 만나
      서로의 민증을 대조해 보면.... 결국 다른 번호로 구분 됩니다.

 - 기본키는 하나 이상의 컬럼이 그룹화 되어 키본키로도 쓰일 수도 있습니다.

 

2. 암묵적 성격

 - 기본키를 추가할 때에는 기본키가 되는 컬럼 또는 컬럼의 그룹에 대하여 자동으로 단일의 B-트리 인덱스가 생성됩니다.

 - 테이블은 기본키를 하나까지만 가질 수 있습니다.

 - 기술적 측면에서 기본키는 단일 값(Unique)하고 not Null(Null 값 비허용)이면 기능적으로 동일하게 동작은 하지만,
   실제적으로 기본키처럼 구분되는건 오직 하나입니다. 즉, 다 똑같은 Unique하고 not Null 이라고 기본키가 되는게 아닙니다.
 - 관계형 DB 이론상 모든 테이블은 반드시 하나의 기본 키를 가져야 합니다. 
    이런 룰을 PostgreSQL에서 꼭 그렇게 따라야할 필요는 없습니다만, 보통 따라주는게 이게 최선입니다.(시크린 가든에... 현빈..)

출처 - http://blog.naver.com/meelong0?Redirect=Log&logNo=140122113670 

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

여러 시스템들을 컨설팅하면서 발견하는 문제점 중 하나는 primary key가 없거나 잘못 정의되어 있는 것입니다. Primary key를 제대로 정의하는 것은 데이터베이스 디자인에 있어서 매우 중요한 출발점입니다.
야밤에 잠도 안 오고 하여 기본 키(primary key)에 대해서 아주 기본적인(^^) 얘기를 몇 자 적어볼까 합니다.
Primary key란 행을 고유하게 구분해 주는 최소의 정보입니다. 모든 테이블에는 primary key가 있어야 하며, 오직 하나의 primary key만 존재할 수 있습니다. 그리고 그 하나의 primary key는 단일 컬럼으로 구성될 수도 있고 둘 이상의 다중의 컬럼들로 구성될 수도 있습니다. 만일 어떤 하나의 테이블에 primary key 역할을 할 수 있는 컬럼 또는 컬럼들의 그룹이 여러 개 있다면 그 컬럼 또는 컬럼들의 그룹을 candidate key라고 합니다. 하나의 테이블에 여러 개의 candidate key들이 존재할 수 있습니다. 가령 회원 테이블에 각각의 회원에게 고유하게 부여되는 (회원번호) 컬럼과 회원의 (주민등록번호) 컬럼, 그리고 회원이 회원가입 시에 선택하면서 회원별로 고유한 회원의 (로그인ID) 컬럼이 존재한다면 이 테이블에는 세 개의 candidate key가 존재하는 겁니다. 그렇지만 이 세 개의 candidate key 중에서 오직 하나의 candidate key 만이 primary key로 간택(^^) 받을 수 있답니다. 참고로 (회원번호) 컬럼을 primary key로 선택했다면 (회원번호) 컬럼은 회원 테이블의 primary key가 되는 것이고, primary key로 뽑히지 못한 (주민등록번호) 컬럼과 (로그인ID) 컬럼은 alternate key가 됩니다.
어떤 분의 블로그에 "다시 보자 기본키"라는 글이 있어서 한번 들어가 보았더니, 내용인즉슨 "무지 느려서 잘 보았더니 primary key가 없더라, 그래서 primary key를 만들어 주었더니 잘 수행되더라. Primary key의 유무가 무지한 성능 차이를 보이더라"는 내용의 글이었습니다. 여러분들 중에서도 테이블에 primary key를 만들어 주고 나니까 성능이 현저하게 향상되는 경우를 경험하신 분들이 계실 겁니다. 테이블에 primary key를 생성하면 성능이 현저하게 향상되는 것은, primary key를 정의하면 물리적으로 uniqueness를 보장하기 위하여 unique index가 만들어지기 때문입니다. 일반적으로 primary key를 기준으로 데이터를 selecct 한다거나 primary key를 기준으로 다른 컬럼(들)의 값을 update 또는 delete하는 작업이 흔히 수행되기 때문에 테이블에 primary key를 정의해 주면 where 조건절에 primary key가 SARGs(Search Arguments)로 사용된 쿼리들의 성능은 현저하게 향상됩니다.
불행히도, 테이블에 candidate key들이 2,3개나 있음에도 불구하고 primary key를 정의하지 않은 경우들을 간혹 볼 수 있습니다. 그런 경우 primary key를 생성하지 않아서 primary key를 사용하는 쿼리들의 성능이 나쁜 것은 물론이며, 테이블에 잘못된 중복 데이터들이 저장됨으로 인하여 데이터 무결성까지 손상되어 있는 비극적인 상황까지 발전한 경우도 있습니다. 테이블에서 각각의 행들을 고유하게 구분해 주는 컬럼 또는 컬럼들의 그룹을 찾아서 primary key를 만들어 주는 것은 반드시 빠뜨려서는 안되는 매우 기본적인 작업입니다.
여담으로, primary key 컬럼이 반드시 테이블의 첫 번째 컬럼이어야 하는 것은 아닙니다. 테이블을 만들고 나서 보니 테이블의 두 번째 컬럼이 primary key라고 해서 슬퍼하지 않으셔도 됩니다. ^ ^ 그렇지만 관례상 primary key 컬럼을 테이블의 첫 번째 컬럼으로 배치하는 것이 일반적입니다.
CREATE TABLE 명령어를 사용하여 테이블을 만들어 줄 때 꼭 잊지 마십시오. Candidate key 중 하나를 primary key로 정의해야 한다는 것을요. 그리고 다음과 같이 CONSTRAINT 절을 사용하여 primary key를 정의하면 됩니다. 이 때 이름은 여러분의 시스템에서 표준화한 명명 규칙이 있다면 그 명명 규칙을 따라서 여러분이 정하시면 되고, primary key 컬럼(들)을 clustered index로 정할지 아니면 nonclustered index로 정할지는 인덱스 튜닝 기준에 따라 정하면 됩니다.
CREATE TABLE dbo.SalesPerson 
(   EmpNo    smallint       NOT NULL,
    EmpName  varchar  (25)  NOT NULL 
CONSTRAINT  PK_SalesPerson  PRIMARY KEY CLUSTERED (EmpNo) )
GO
만일 테이블을 만들 때 깜빡하고 primary key 제약 조건을 만들어 주는 것을 잊어버리셨다 해도 슬퍼하지 마세요. ALTER TABLE이 있습니다.
ALTER TABLE SalesPerson
ADD CONSTRAINT PK_SalesPerson PRIMARY KEY CLUSTERED (EmpNo)
GO
그런데 가끔 primary key가 안 만들어진다고 하시는 분들이 계시는데, 이미 primary key 컬럼에 중복 값이 저장되어 있거나 아니면 primary key로 정의하고자 하는 컬럼 또는 컬럼들이 NULL 허용으로 정의되어 있기 때문입니다. Primary key 컬럼은 반드시 NOT NULL로 정의하셔야 합니다. Primary key 컬럼은 NOT NULL 이어야만 하며, (primary key를 만드는 데 장애물이 되지는 않습니다만) 길이가 짧고 변경이 발생하지 않는 컬럼이어야 합니다. Microsoft에 null 허용 컬럼에도 primary key를 만들 수 있도록 해 달라고 하셔도 소용없습니다. ^ ^  Primary key 값은 절대로 null이어서는 안된다는 규정은 ANSI에서 정의한 규정이기 때문입니다.
또 이런 경우도 있습니다. 테이블에 primary key가 만들어져 있기는 한데, 사족을 달고 있는 primaru key들도 종종 볼 수 있습니다. primary key는 행을 고유하게 구분하는데 필요한 최소의 컬럼만 포함시켜야 합니다. 그렇다면 primary key가 불필요한 사족을 달고 있으면 어떤 문제가 발생할까요? 가령 (로그인ID) 하나로도 primary key가 되는데 (로그인ID, 가입일자)라는 composite key를 primary key로 생성했다면 어떤 문제가 발생할지 한번 생각해 보셔요. ~~~

출처 - http://blog.naver.com/newcomsa?Redirect=Log&logNo=30082713932

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







Posted by linuxism
,

mysql index 설정

DB/MySQL 2012. 3. 30. 11:09


mysql select 문에서 where 절을 포함한 쿼리의 실행 타임이 길게 나와 웹페이지 로딩시
지연 현상이 발생하는 경우가 종종 있습니다.
slow 로그에 남아 있는 쿼리문을 확인하여 인덱스가 걸려 있는지 확인을 합니다.
 
인덱스 보기
show index from 테이블명
  
인덱스 추가
alter table 테이블명 add index 인덱스명 (칼럼명);
  
인덱스 삭제
alter table 테이블명 drop index 인덱스명;



1. 추가하여 만들기
CREATE INDEX <인덱스명> ON <테이블명> ( 칼럼명1, 칼럼명2, ... );

2. 테이블 생성시 만들기
끝에....
INDEX <인덱스명> ( 칼럼명1, 칼럼명2 )
UNIQUE INDEX <인덱스명> ( 칼럼명 ) --> 항상 유일해야 함.

3. 이렇게도 생성한다
ALTER TABLE <테이블명> ADD INDEX <인덱스명> ( 칼럼명1, 칼럼명2, ... );

4. 인덱스 보기
SHOW INDEX FROM <테이블명>;

5. 인덱스 삭제
ALTER TABLE <테이블명> DROP INDEX <인덱스명>;


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

인덱스 추가 전략

인덱스 추가 전략은 다음과 같다.

 

1. 제일 많이 돌릴 쿼리를 조사한다.

 

2. 위에서 조사한 쿼리에서 인덱스가 필요한지 검토한다. 이 때에 데이터 삽입, 갱신 연산도 같이 고려해야 한다.

  - 어떤 컬럼에 고유 값이 많은지, 어떤 컬럼이 WHERE 절에 가장 많이 나타나는지 검토한다.

  - 고유 값이 많은 컬럼의 인덱스는 매우 선택적이다.

  - 인덱스를 설계할 때는 기존 쿼리에 필요한 인덱스 유형만 생각하지 말고 쿼리 최적화도 함께 고려해야 한다.

 

3. 여러 종류의 쿼리가 있어서 완벽한 인덱스 추가하지 못 하는 경우에는 타협을 보아야 한다.

  - 인덱스 추가로 속도가 저하될 쿼리가 있다면 쿼리를 수정할 수 없는지 생각해 보자.

  - 최적의 타협안을 찾으려면 쿼리와 인덱스를 함께 최적화해야 한다.

 

                                                                                                                                               

 

인덱스를 추가해야 하는 경우는 다음과 같다.

 

1. 응답 시간이 오래 걸리는 쿼리를 위한 인덱스를 추가하자.

2. 부하가 가장 많이 걸리는 쿼리를 위한 인덱스를 추가하자.

3. 가능하면 새 인덱스를 추가하는 것보다는 기존 인덱스를 확장하는 것이 좋다.


출처 - http://blog.naver.com/websearch?Redirect=Log&logNo=70106231179


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

[펌]  http://www.mysqlkorea.co.kr/sub.html?mcode=develop&scode=01&m_no=21714&cat1=7&cat2=219&cat3=253&lang=k

 

7.4.5. MySQL의 인덱스 사용 방법

인덱스는 특정 컬럼 값을 가지고 있는 열을 빨리 찾기 위해서 사용된다인덱스를 사용하지 않는다면, MySQL은 첫 번째 열부터 전체 테이블에 걸쳐서 연관된 열을 찾아야만 한다테이블이 크면 클수록 비용도 늘어나게 되는 것이다만일 테이블이 쿼리에 있는 질문 컬럼에 대한 인덱스를 가지고 있다면, MySQL은 모든 데이터를 조사하지 않고 데이터 파일 중간에서 검색 위치를 재빨리 알아낼 수가 있다만일 테이블이 1,000개의 열을 가지고 있다면이것은 최소 100배의 속도 향상을 가질 수가 있다만일 대부분의 열을 접속할 필요가 있는 경우라면순차적인 읽기 (sequential read)가 더 빠르게 되는데그 이유는 이 방법이 디스크 검색을 최소화 하기 때문이다.

대부분의 MySQL 인덱스 (PRIMARY KEYUNIQUEINDEX그리고 FULLTEXT)는 B-트리에 저장된다하지만공간 데이터 (spatial data)가 R-트리를 사용하고MEMORY 테이블도 해시 인덱스 (hash indexes)를 지원한다는 점에 대해서는 함께 알아 두기 바란다.

스트링은 자동적으로 접두사- (prefix-)와 끝-공간 (end-space)을 압축한다.

MySQL은 다음과 같은 경우에 인덱스를 사용한다:

  • WHERE 구문과 일치하는 열을 빨리 찾기 위해.
  • 열을 고려 대상에서 빨리 없애 버리기 위해만일 여러 개의 인덱스 사이에서 선택을 해야 한다면, MySQL은 보통 최소의 열을 찾는 인덱스를 사용한다.
  • 조인 (join)을 실행할 때 다른 테이블에서 열을 추출하기 위해.
  • 특정하게 인덱스된 컬럼 key_col을 위한 MIN() 또는 MAX() 값을 찾기 위해이것은 인덱스에서 key_col 전에 발생하는 모든 키 부분의 WHERE key_part_N = constant를 사용할 수 있는지를 검사하는 프리 프로세서 (pre-processor)에 의해 최적화 된다이와 같은 경우, MySQL은 각각의 MIN() 또는 MAX() 수식에 대해서 단일 키 룩업 (lookup)을 실행해서 상수로 대체한다모든 수식이 상수로 대체가 되면쿼리는 즉시 리턴 된다예를 들면:
SELECT MIN(key_part2),MAX(key_part2)
  FROM tbl_name WHERE key_part1=10;
  • 사용할 수 있는 키의 최 좌측 접두사 (leftmost prefix)를 가지고 정렬 (sorting) 및 그룹화 (grouping)를 하기 위해 (예를 들면,ORDER BY key_part1key_part2). 만일 모든 키 부분이 DESC 다음에 나온다면그 키는 역순으로 읽혀진다.
  • 데이터 열을 참조하지 않는 상태로 값을 추출하기 위해서 쿼리를 최적화 하는 경우도 있다만일 쿼리가 숫자로만 이루어진 테이블 컬럼만을 사용하고 몇몇 키에 대해서는 최 좌측 접두사를 가지고 있다면선택된 값은 인덱스 트리로부터 매우 빠른 속도로 추출이 될 것이다:
SELECT key_part3 FROM tbl_name 
  WHERE key_part1=1

여러분이 아래와 같은 SELECT 명령문을 입력했다고 가정하자:

mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

만일 다중-컬럼 인덱스가 col1 과 col2에 존재한다면적당한 열을 직접 가져올 수가 있다만일 별개의 단일-컬럼 인덱스가 col1 col2에 존재한다면옵티마이저는 어떤 인덱스가 가장 적은 열을 찾아내는지를 알아낸 후에 그 인덱스를 사용해서 열을 패치 (fetch)함으로써 가장 제한적인 인덱스를 찾으려고 시도를 한다.

만일 테이블이 다중-컬럼 인덱스를 가지고 있다면옵티마이저는 인덱스의 최 좌측 접두사를 사용해서 열을 찾는다예를 들면만일 여러분이 세개의 컬럼 인덱스를 (col1, col2, col3)에서 가지고 있다면여러분은 (col1)(col1, col2)그리고 (col1, col2, col3)에서 검색 기능이 있는 인덱스를 가지게 되는 것이다.

컬럼이 인덱스의 최 좌측 접두사를 가지고 있지 않다면, MySQL은 부분 인덱스를 사용할 수 없게 된다아래와 같은 SELECT 명령문을 가지고 있다고 가정하자:

SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
 
SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

만일 (col1, col2, col3)에 인덱스가 하나 존재한다면처음 두 개의 쿼리만이 인덱스를 사용하게 된다세 번째와 네 번째도 인덱스된 컬럼을 가지고 있기는 하지만(col2) 와 (col2, col3) 는 (col1, col2, col3)의 최 좌측 접두사가 아니다.

B-트리 인덱스는 =>>=<<=또는 BETWEEN 연산자를 사용하는 수식에서 컬럼 비교를 위해 사용될 수 있다또한LIKE에 대한 인수가 와일드 카드 문자로 시작되지 않는 상수 스크링일 경우에는LIKE 비교를 위해서도 이 인덱스를 사용할 수 있다예를 들면아래의SELECT 명령문은 인덱스를 사용한다:

SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';

첫 번째 명령문에서 보면'Patrick' <= key_col < 'Patricl'을 가지고 있는 열만이 고려되었다두 번째 명령문에서는'Pat' <=key_col < 'Pau'를 가지고 있는 열만이 고려된다.

아래의 SELECT 명령문은 인덱스를 사용하지 않는다:

SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE other_col;

첫 번째 명령문의 경우LIKE 값이 와일드 카드 문자로 시작된다두 번째 명령문에서는LIKE 값이 상수가 아니다.

만일 여러분이 ... LIKE '%string%'을 사용하고string 3개의 문자 보다 길다면, MySQL 은 스트링용 패턴을 초기화 시키기 위해Turbo Boyer-Moore algorithm 을 사용하게 되며이 패턴을 사용해서 검색을 보다 빠르게 실행한다.

col_name IS NULL을 사용하는 검색은 col_name 이 인덱싱 되는 경우에는 적용할 수가 있다.

WHERE 구문에 있는 모든AND 레벨에 해당하지 않는 모든 인덱스는 쿼리를 최적화하는데 사용되지 않는다달리 표현하면인덱스를 사용하기 위해서는인덱스의 접두사가 반드시 모든 AND 그룹에서 사용되어야 한다는 것이다.

아래의 WHERE 구문은 인덱스를 사용한다:

... WHERE index_part1=1 AND index_part2=2 AND other_column=3
    /* index = 1 OR index = 2 */
... WHERE index=1 OR A=10 AND index=2
    /* optimized like "index_part1='hello'" */
... WHERE index_part1='hello' AND index_part3=5
    /* Can use index on index1 but not on index2 or index3 */
... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;

아래의 WHERE 구문은 인덱스를 사용하지 않는다:

    /* index_part1 is not used */
... WHERE index_part2=1 AND index_part3=2
 
    /*  Index is not used in both parts of the WHERE clause  */
... WHERE index=1 OR A=10
 
    /* No index spans all rows  */
... WHERE index_part1=1 OR index_part2=10

MySQL이 인덱스를 사용할 수 있을 지라도 이것을 사용하지 않는 경우도 있다. MySQL이 인덱스를 사용하기 위해서는 테이블의 거의 모든 열을 접속할 필요가 있다고 옵티마이저가 판단할 경우가 이에 해당한다. (이와 같은 경우에는테이블 스캔이 속도가 더 빠르다.) 하지만,만일 이러한 쿼리가 LIMIT를 사용해서 열의 일부분만 추출하는 경우에는, MySQL은 인덱스를 사용하게 되는데그 이유는 결과를 리턴하기 위해서 찾아야 하는 열의 숫자가 작기 때문에 그 만큼 속도가 빠르기 때문이다.

해시 인덱스 (Hash indexes)는 위에서 설명한 것과는 다소 다른 특징을 가지고 있다:

  • 이것은 = 또는 <=> 연산자를 사용하는 등식 비교에 대해서만 사용된다 (하지만 매우 빠름). 이것은 값의 범위를 찾기 위한 < 와 같은 비교 연산자와는 같이 사용되지 않는다.
  • 옵티마이저는 ORDER BY 연산 속도를 증가 시키기 위해 이것을 사용할 수가 없다. (이런 타입의 인덱스는 다음 순서의 엔트리를 위한 검색용으로 사용될 수 없다.)
  • MySQL은 두 개의 값 사이에 얼마나 많은 열이 있는지를 추정할 수 없다 (이것은 사용한 인덱스가 어떤 것인지를 결정하기 위한 범위 옵티마이저가 사용하는 것이다).
  • 단지 전체 키만이 열에 대한 검색을 할 수가 있다. (B-트리 인덱스를 사용한다면키의 최 좌측 접두사가 열 검색에 사용될 수가 있다.)

    [출처] MYSQL 인덱스|작성자 빼빼로

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

mysql 인덱스와 외래키 걸기

alter table [tablename] add index [컬럼명];

이렇게 인덱스를 걸어놓은 컬럼에만 foreign key 를 걸수 있다.

인덱스를 걸어놓지 않고 외래키를 걸면 SQL 문법 에러가 난다.


foreign key 거는 문법은

alter table [테이블명] add constraint foreign key ( [컬럼명] ) references [테이블명] ( [컬럼명] )


이고 디폴트는 no action 이다.

 

맨 뒤에 on delete, on update 문을 추가해서

cascade, restrict, set null, set default 등의 옵션을 줄수있다.

 

각각이 어떤 역할인지는 조금 생각하면 바로 알수있다.

 

참고로 mysql 4.0.x 대 버전에서는 SQL 에 컬럼명을 기재할때 그냥 쓰면되는데

5.0 대에서는 ` ` 로 둘러싸야 된다.

출처 - http://blog.naver.com/declspec?Redirect=Log&logNo=10099470747

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

중소형 DBMS mysql

 

보통의 DBMS 에는 index 를 걸수 있다 필드에....

 

이 index란 것은 주소와 같은 개념이다....

 

어떤 테이블에 여러 필드가 존재하고 각 필드에는 row 마다 다른 정보들이 들어가 있다..

 

여기서 특정 정보를 읽어 오기 위해서는 1번 주소부터 끝나는 주소까지 순차적으로 검색을 하게 된다.

 

이렇게 되면 100개의 데이터가 있고 그중 찾으려는 데이터가 100번째에 있다면 100번의 접근이 필요하다...

 

물론 운좋게 찾으려는 데이터가 10번째에 있다면 10번만 접근하게 된다.

 

이럴때 index를 해당 필드에 걸어 준다면 해당 필드값들은 b-tree 라는 자료 구조로 정리되게 된다. 데이터들이 섞이는것이아니라 그 데이터를 가리키는 주소를 b-tree 라는 형태로 저장을 해두는 것이다.

 

그래서 index가 걸린 필드를 검색하게 되면 필드에 직접 접근하는것이 아니라 b-tree를 저장해둔 곳으로 우선 접근해서 해당 데이터의 주소를 얻어 온다..

 

그런후에 그 주소로 직접 접근하게 된다.

 

이런식으로 접근하는 횟수가 많이 줄게 되기때문에 select 시에 많은 효과를 볼수가 있다..

 

그러나 index가 있으면 insert 또는 update 시에는 데이터 넣는 작업 외에도 b-tree를 재정의 해서 저장해야 하기때문에 속도가 느려지게 됨에 유의해야 한다.

 

또한 검색 조건에 맞는 index를 걸어야 좋은 효과를 볼수 있다.

[출처] mysql index 의 개념|작성자 다크몽

출처 - http://blog.naver.com/dark0111?Redirect=Log&logNo=30017199486 

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


어떤 DBMS라도 인덱스를 사용할 수 있죠. 그보다는 인덱스를 사용할 수 없으면 DBMS라고 부르기 힘들져.

mysql에서 index사용법에 대하여 몇가지 썰을 풀어 볼까 합니다.
누구나 다 아는 야그일것 같은데 헛튼짓 하는것 아닌지 모르겟네여.


다음과 같은 member 테이블을 가지고 놀아 봅시다.

CREATE TABLE member (
id CHAR(10),
name CHAR(20),
age int,
level CHAR(10)
);

요 테이블은 index가 잡혀 있지 않죠. 

다음과 같은 select문에 대해서 잘 동작합니다.
select * from member where id = 'myid';

별 문제 없는것 같습니다. 그런데 레코드 수가 좀 많아 지면 query해오는데 시간이 점점 늘어 나져. 그 이유는 member 테이블에 있는 모든 레코드에 대하여 id가 'myid' 인지 전부 비교합니다.(full scan) 레코드가 늘어 날수록 시간은 점점 오래 걸리겠죠.

그리고 다음과 같은 select의 경우에는 시간이 오래 걸리져.
select * from member where id id ='myid' order by id;

id란 필드에 대한 값으로 전체를 sort해야 되기 때문이져.


테이블을 변경해 봅시다.

CREATE TABLE member (
id CAHR(10) NOT NULL DEFAULT '',
name CHAR(20),
age INT,
level CHAR(10),
INDEX myindex1 (id)
);

달라진것은 id 필드에 NOT NULL DEFAULT ''이 추가 됬고, 마지막에 index myindex1(id)라는 항목이 추가 됐네여. id라는 필드에 대하여 인덱스를 설정한 것입니다. myindex1은 인덱스의 이름일 뿐입니다. 사용자가 임의로 결정해 줍니다.
NOT NULL이 추가된 것은 index로 사용될 필드는 반드시 NOT NULL이어야 하기 때문이고, DEFUALT ''는 입력값이 없을 때 null이 아닌 어떤값을 디펄트로 사용하겠다는 겁니다.

그냥 index로 사용될 필드는 반드시 NOT NULL과 DEFAULT를 설정해야 된다고 알고 있음 되겟네여.


이렇게 index가 설정되면 id의 순서에 따라 정렬된 index를 가지기 때문에 레코드 수의 증가와 거의 관계없이(사실은 관계있지만 없다고 하겠습니다.) query시간이 일정합니다. 그리고 당근 order by id와 같이 정렬이 필요한 경우에도 따로 sort해줄 필요 없기 때문에 퀘리 시간이 짧지여.

select의 키가 되는 필드는 당연히 보다는 반듯이 index를 잡아 주어야 합니다.


이제 다음과 같은 select문을 생각해 봅시다.
select * from member where name='아무개' age > 20 order by id;

name과 age 필드가 where문에서 사용되었네여. 그렇다면 다음과 같이 name과 age도 index로 잡아 줍니다.

CREATE TABLE member (
id CHAR(10) NOT NULL DEFAULT '',
name CHAR(20) NOT NULL DEFAULT '',
age INT NOT NULL DEFAULT 0
level CHAR(10),
INDEX myindex1 (id),
INDEX myindex2 (name),
INDEX myindex3 (age)
);

별로 어렵지 않죠. 

그렇다면 위의 CREATE문과 다음의 CREATE문은 어떤 차이가 있을 까여?

CREATE TABLE member (
id CHAR(10) NOT NULL DEFAULT '',
name CHAR(20) NOT NULL DEFAULT '',
age INT NOT NULL DEFAULT 0
level CHAR(10),
INDEX myindex1 (id, name, age)
);

위의 두개의 CREATE문으로 생성된 member 테이블은 다음과 같은 select에 대해서는 똑같은 동작을 합니다.
select * from member where id = 'myid' order by id;
select * from member where id = 'myid' and name='아무개' order by id;

하지만 다음의 select문에대해서는 서로 다르게 동작합니다.

select * from member where name='아무개';

음.. 두번째 member 테이블에서도 name 필드가 인덱스에 포함되었는데 왜 그럴까...

첫번째의 member 테이블에서는 id, name, age가 각기 다른 index로 잡혀 있었습니다. 그런데 두번째 member 테이블에서는 id, name, age가 하나의 index로 잡혀 있습니다.
두번째 테이블의 경우 id, name, age의 값이 concate된 값이 index로 작용합니다.
name이란 필드 하나는 index의 역활을 하지 못합니다.

그래서 name이나 age가 따로 키값으로 사용되는 select문에서는 인덱스의 덕을 보지 못하져.

하지만 다음과 같이 id, name, age가 순차적으로 검새될 때는 인덱스의 덕을 봅니다.
select * from member where id = 'myid';
select * from member where id = 'myid' and name='아무개';
select * from member where id = 'myid' and name='아무개' and age=20;

위의 sql의 where 부분은 다음과 같이 작용됩니다.(다음 구문은 sql이 아닙니다. 단지 설명을 위해서) 
where id = 'myid'
where id+name = 'myid아무개'
where id+name+age = 'myid아무개20'

그렇다면 다음과 같은 select의 경우는 인덱스의 덕을 볼까여?
select * from member where id like 'my%' ane name='아무개';

id like 'my%'구문은 정규표현식과 비슷합니다. id가 'my'로 시작되는 값을 의미합니다.

적용되는 것을 다시 적어 보면 
where id+name like 'my%아무개'

일단은 id부분에서는 덕을 봅니다. 하여간에 id부분이 my로 시작되는 레코드에 대해서 검색을 할테니까여 그러나 name이 '아무개'인 부분은 인덱스의 덕을 보지 못합니다. id필드값이 my로 시작되는 모든 레코드에 대하여 역시 풀스켄합니다.

테이블의 여러 필드가 인덱스로 잡혔을 때 동작하는 원리를 설명하겠습니다.
feild1, field2, field3가 인덱스로 잡혀 있을때 다음과 같은 where문이 있다고 합시다.
where field1 = 'value1' and field2 like 'value2%' and field3 > value3

1. field1의 값이 'value1'인 레코드의 레퍼런스 리스트를 구합니다. 이때 field1의 인덱스를 사용합니다. 요 리스트는 역시 field2와 field3에 대한 인덱스를 가지고 있지여.
2. 위에서 구한 리스트에서 field2의 값이 'value2'로 시작되는 레코드의 레퍼런스 리스트를 구합니다. 이때도 역시 field2의 인덱스를 사용해서 구합니다.
3. 다시 위에서 구한 리스트에서 field3의 값이 value3보다 큰 레코드의 레퍼런스 리스트를 구합니다.
4. 최종적으로 구한 리스트의 레퍼런스를 가지고 각 레퍼런스가 가리키는 레코드의 값을 반환합니다.


!!! 테이블의 index설정에 따라 시스템의 퍼포먼스가 엄청나게 차이납니다.
!!! 인덱스 설정은 엄!청! 중요합니다. 

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

 

인덱스 정보 보기

mysql> SHOW INDEX FROM tablename

[출처] MYSQL INDEX에 관하여..|작성자 디플

출처 - http://blog.naver.com/rsr10?Redirect=Log&logNo=130007347356















Posted by linuxism
,

 


noveljsp2_chap12.ppt

출처 - jabook.org





 

JSTL (JSP Standard Tag Library)

     

: JSP 페이지를 작성할 때 유용하게 사용할 수 있는 여러가지 커스텀 액션과 함수를 포함하는 라이브러리

1. 프로그램 로직 구사(변수선언, 제어문)

2. JSP 페이지 호출

3. 날짜나 시간, 숫자 데이터의 포맷 지정

4. 데이터베이스로의 입력, 수정, 삭제, 조회 기능

5. XML 문서의 처리

: 5개의 라이브러리로 구성(코어, 포메팅, 데이터베이스, XML, 함수)

Library

Prefix(접두어)

core

c

format

fmt

database

sql

XML

x

function

fn

     

 

1. JSTL core

     

: JSTL의 가장 핵심적인 기능을 제공하는 Library

: 제어문, 변수

: <%@ taglib prifix="c" uri="http://java.sun.com/jsp/jstl/core" %>

: tag list

title

core

   

변수 설정 및 삭제 태그

<c:set>

<c:set var="변수명" value="설정값" target="객체" property="값" scope="범위" >

  • 지정된 변수에 값을 저장하는 태그
  • 특정 property에 값을 지정할 경우 target에 객체 표시, property에 값을 지정

   

<c:remove>

<c:remove var="변수명" scope="범위" >

  • 설정된 속성(변수, 객체)을 제거

조건 처리 태그

<c:if>

<c:if test="조건" var="변수명" scope="범위" >

  • 자바의 if와 같은 역할

   

<c:choose>

     

   

< c:choose>

<c:when test="조건"> </c:when>

<c:otherwise> </c:otherwise>

</c:choose>

  • 자바의 switch와 같은 구문

반복 처리 태그

<c:forEach>

<c:forEach itmes="객체명" begin="시작인덱스" end="끝인덱스"

step="증감식" var="변수명" varStatus="상태변수" >

  • 자바의 for

   

<c:forTakens>

   

<c:forTokens items="객체명" delims="구분자" begin="시작인덱스"

end="끝인덱스" step="증감식" var="변수명" varStatus="상태변수" >

예외 처리 태그

<c:catch>

<c:catch var="변수명" >

  • 예외가 발생할 경우 예외사항을 변수에 저장
  • 예외사항을 출력 : 변수.message

     

     

ex ) tag list 예제

<c:set>

   

  

<c:set> scope이용

   

  

<c:if>

   

  

<c:choose>

   

  

<c:forEach>

   

  

<c:forEach> items 이용

   

  

<c:forTokens>

   

  

     

    

출처 - http://blog.naver.com/lagi1101?Redirect=Log&logNo=90121522958

 

'Development > JSP & Servlet' 카테고리의 다른 글

jsp/servlet scope  (0) 2012.05.14
JSP 소스 사이트  (0) 2012.05.07
jsp - EL(Expression Language)  (0) 2012.03.28
getParameter와 getAttribute 차이  (0) 2012.03.28
JSP에서 JSTL과 EL(Expression Language) 사용하기  (0) 2012.03.28
Posted by linuxism
,