database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 4697 게시물 읽기
No. 4697
[팁] timestamp 자료형과 인덱스
작성자
김상기(ioseph)
작성일
2003-05-08 11:13
조회수
2,708

timestamp 자료형을 사용할 때 null 값은 인덱스를 사용해서 찾지 못한다는 사실을 알았네요. (약 3년전에 알았던 내용인데, 까먹었다가 오늘 다시 알게 되어서 이번에는 안 까먹으려고 남겨둡니다)

 

create table t (

주문번호 int,

승인날짜 timestamp

);

create index t_승인날짜_i on t (승인날짜);

 

이런 테이블이 있을 때,

'아직 승인되지 않았는 주문을 찾아라'는 쿼리를

 

select * from t where 승인날짜 is null

 

이놈을 사용하면 될 것이다고 생각했었는데, 이게 아니였군요. :(

 

즉, PostgreSQL 에서는 인덱스를 사용하려면 어떤값이 반드시 있어야합니다.

승인되지 않았는 자료는 '0001-01-01 00:00:00' 형태일지라도 어떤 값이 있어야하네요.

 

즉, select * from t where 승인날짜 = '0001-01-01 00:00:00'

 

이런 형태여야합니다.

 

3년전에 이렇게 만들어놓고는 이번에 스키마 수정하면서 응용프로그램 쿼리가 지저분해 진다고 null 로 바꾸었더니만 .... 아무튼 머리가 나쁘면 손발이 고생하는 것은 분명한 것 같습니다.

이 글에 대한 댓글이 총 4건 있습니다.

create index i_name on tbl_name where col is null;

 

이런식으로 인뎃스를주니 가능하네요.

 

7.3.2에서만 시험해보았는데 다른버젼은 모르겠구요

 

timsorig=# create index len_i on len(cp_num) where cp_num is null;

CREATE INDEX

timsorig=# explain select count(*) from len where cp_num is null;

QUERY PLAN

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

Aggregate (cost=66729.52..66729.52 rows=1 width=0)

-> Index Scan using len_i on len (cost=0.00..66687.40 rows=16848 width=0)

Filter: (cp_num IS NULL)

(3 rows)

 

timsorig=# explain select count(*) from len where cp_num =3;

QUERY PLAN

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

Aggregate (cost=112714.31..112714.31 rows=1 width=0)

-> Seq Scan on len (cost=0.00..112672.19 rows=16848 width=0)

Filter: (cp_num = 3)

(3 rows)

황치영님이 2003-05-08 21:04에 작성한 댓글입니다.

황치영님의 방법을 까먹고 있었군요. :)

 

덧붙혀서,

create index 에서 where 절을 사용한 부분 인덱싱은 실질적인 작업 쿼리에서 그 where 절만을 사용한다는 전재 아래에서 사용되어집니다.

 

따라서 select count(*) from len where cp_num =3 처럼 인덱싱을 사용하지 못하는 쿼리를 위해서, 인덱스를 두개 만들어두면 되겠네요. :)

 

멋진 해결책입니다. 고맙습니다.

정리 원문을 다시 정리하면,

 

select * from t where 승인날짜 is null

쿼리도 사용되어지고,

 

select * from t where 승인날짜 between '2002-01-01 00:00:00' and '2002-01-31 23:59:59'

이런 쿼리도 같이 사용되어질 것이라면,

 

create index t_승인날짜_i on t (승인날짜) where 승인날짜 is null;

create index t_승인날짜2_i on t (승인날짜);

 

이렇게 두개의 인덱스를 함께 만들어두면 될 것같네요.

김상기(ioseph)님이 2003-05-09 02:49에 작성한 댓글입니다.

index 를 두개 만든다는건 그리 권장할만한

사항이 못됩니다.

postgresql의 인덱스는 부분 인덱스라 할지라도

테이블 화일의 사이즈와 같은 크기를 가지게 됩니다.

일시적으로 사용했다가 버리는 인덱스라면

문제가 없겠지만

지속적인 사용에는 많은 코스트가 필요 하게 됩니다.

 

create table t (

주문번호 int,

승인날짜 timestamp default 0 is not null

);

create index t_승인날짜_i on t (승인날짜);

 

select * from t where 승인날자 = 0;

 

제 경우에는 보통 이런식으로 사용합니다.

 

timestamp 보다는 int4 더 많이 쓰기도 합니다.

 

참고가 되셨길 바랍니다. :-)

zetop님이 2003-05-24 07:38에 작성한 댓글입니다.

실세계에서 날짜/시간을 db에서 timestamp로 쓸 것인가? 아니면, 기타 다른 자료형(int, char)으로 쓸 것인가?는 그 자료가 어떤 식으로 사용될 것인가에 달려있습니다.

 

예를 들어서,

최근 1주일간, 최근 3일간 ... 이런식의 자료를 뽑는 일이 빈번한 자료라면, 당연히 정수형이나, 문자열보다는 timestamp형이 더 타당합니다. timestamp 형의 +,- 연산이 SQL의 멋진 기능이니.

 

하지만, 저장되는 자료가 반드시 일/월/년단위로만 뽑혀진다면, 즉, 2003년 5월 자료 모두 .. 이런식으로 움직일 것이라면, 문자열 자료형도 꽤 괜찮은 선택입니다. like 문의 문자열 인덱싱도 탁월한 선택이니.

 

아쉽게도 PostgreSQL의 timestamp 형은 default 값으로 0을 가질 수 없습니다.

지난번 작업했던 방식은 timestamp형으로 default를 '0001-01-01 00:00:00' 이 값을 두었지요. 그리고 당연히 인덱스를 하나 두었지요. 이것이 얼마나 많은 응용프로그램의 코딩량을 증가시키는지....

 

'최근 3일간 승인되지 않은 주문을 찾아라' 와 같은 기간이 존재하고, null이 필요한 자료구조라면, 부득이 두개의 인덱싱을 사용하는 것이 여러모로 나을 것같습니다.

 

더 자세한 이야기 이곳 게시판들의 timestamp 자료형에 대한 이야기를 차근히 살펴보시고, 판단은 각자 알아서.

김상기(ioseph)님이 2003-05-25 06:31에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
4701pg_dumpall 에서 owner 관련 메세지 [1]
성혁
2003-05-10
1535
4699pgsql에서 txt로 뽑기 [1]
뚜리
2003-05-09
1309
4698readline 내게 돌아와줘~ [4]
대훈
2003-05-09
1628
4697[팁] timestamp 자료형과 인덱스 [4]
김상기
2003-05-08
2708
4696pgsql -> mssql로 가져오기
뚜리
2003-05-07
1276
4695[질문] insert 시에 이미 존재하는 값이라면 update 를 하고 싶을때.. [1]
김강린
2003-05-07
1413
4694[질문]php에서 db연결에러 [2]
이정호
2003-05-02
3758
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.018초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다