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 7478 게시물 읽기
No. 7478
인덱스 관련 질문(WHERE조건이 많을 경우)...
작성자
오래된남자(jang2000act)
작성일
2008-07-29 16:41ⓒ
2008-07-29 16:43ⓜ
조회수
8,326

다음의 테이블이 있습니다.


test_table (


time    time_stamp,

user    bytea,

ip        bigint,

name  bytea


)



인덱스는 다음과 같습니다.


all_idx (time, user, ip, name)

user_idx (user, time)

ip_idx (ip, time)

name_idx (name, time)



약 2억5천만건 정도의 데이터가 입력되어 있다고 가정하게 되면...



SELECT 시에 기본 적으로 time 은 where 조건에 항상 들어 갑니다.

이외에 user, ip, name는 사용자 선택에 따라 WHERE 조건에 포함되거나 포함되지 않을 수 있습니다.


사용자가 ip를 지정하였을 경우의 SELECT문은 다음과 같습니다.


SELECT time, user, ip, name FROM test_table 

 WHERE

   time >= '2008-07-09 12:00:00' and 

   time <= '2008-07-10 13:00:00' and

   ip = 1023421

order by time limit 200;


위의 쿼리문이 실행되면 ip_idx 인덱스를 타게 되어 바로 결과가 출력됩니다.


user나 name의 경우에도 바로 출력 됩니다.


이번에 where 조건에 모두 포함되는 경우 입니다.


SELECT time, user, ip, name FROM test_table

 WHERE

   time >= '2008-07-09 12:00:00' and 

   time <= '2008-07-10 13:00:00' and

   ip = 1023421 and

   user = 'test' and

   name = 'oldman'

order by time limit 200;

   

위의 where 조건에 해당하는 값이 결과값에 있다면 바로 결과가 출력됩니다. 인덱스는 all_idx를 타게 됩니다.

만약 user에 test라는 값이 결과 값에 존재하지 않는다면 all_idx를 타지 않고 user_idx를 타게 되던군요.. 마찬가지 결과가 바로 출력됩니다. 물론 아무런 값도 없겠지요.


제가 궁금한 것은요...


가령 where 조건의 IP의 값은 결과 값에 있습니다.

또한 where 조건의  user 값은 결과 값에 있구요..name 역시 마찬가지 입니다.


하지만 위 모두를 and 조건으로 하게되면 결과 값은 없습니다. 2억건이 데이터중에서 개별적으로는 있지만

and를 하게되면 없을 경우 에는 결과값이 굉장히 느리게 나오더라구요... 사실 너무 느려서 끝까지 기다려 보지도 않았습니다.

일일이 다 조합해보느라 굉장히 오래 걸리는 것 같습니다.. 처음부터 끝까지...


어떻게 하면 바로 결과를 볼 수 있을 까요..?


인덱스를 새롭게 줘야 할가요... 아니면... 혹시 Postgresql 설정 중에 시간을 설정하여 쿼리문의 결과가 늦게 되면 설정된 시간에 의해

그냥 쿼리문이 종료되는 ... 그러한 설정은 없나요.. 찾아보니 postgresql.conf에서 statement_timeout 값을 지정해주면 된다고 해서 

해봤는데 되질 않네요...




참고로 postgresql 버전은 8.3.3을 쓰고 있습니다.



제가 구현하려는 것은요.. 테이블 하나에 수억건의 데이터가 쌓여도 인덱스에 의해 어떠한 조건으로도 빠르게 출력되는 방법을 찾고 있습니다.


소중한 답변 정중히 부탁드립니다. 감사합니다.

이 글에 대한 댓글이 총 4건 있습니다.
explain analyze를 사용하셔서 문제되는 쿼리의 결과를 한번 올려주시기 바랍니다.

그리고 쿼리를

explain analyze
SELECT time, user, ip, name FROM test_table
WHERE
   user = 'test' and
   name = 'oldman' and
   ip = 1023421 and
   time >= '2008-07-09 12:00:00' and 
   time <= '2008-07-10 13:00:00'
order by time limit 200;

이렇게 하셔서 쿼리 결과를 한번 올려주시기 바랍니다.
김병석(byung82)님이 2008-07-29 17:23에 작성한 댓글입니다.
이 댓글은 2008-07-29 17:25에 마지막으로 수정되었습니다.
 Limit  (cost=0.00..171.00 rows=10 width=8) (actual time=441076.031..441076.031 rows=0 loops=1)
   ->  Index Scan Backward using all_idx on test_table (cost=0.00..13188706.37 rows=771263 width=8) (actual time=441076.027..441076.027 rows=0 loops=1)
         Index Cond: ((time >= '2008-07-01 00:00:00'::timestamp without time zone) AND (time <= '2008-07-30 23:00:00'::timestamp without time zone) AND (name = 'oldman'::bytea) AND (user = 'test'::bytea) AND (ip = 0))
 Total runtime: 441076.079 ms
(4 rows)
--------------------------------------------------------------------------------------------

explain analyze 한 결과 입니다. where 조건은 약간 틀립니다...

오래된남자(jang2000act)님이 2008-07-29 17:38에 작성한 댓글입니다.

쿼리를 좀 변경해서 테스트 해보시기 바랍니다.



일단..


select time,user,ip,name from test_table as a

inner join 

(

select user from test_table 

where user = 'user'

) as b

on a.user = b.user

inner join 

(

select ip from test_table 

where ip = 'ip'

) as c

on a.ip = c.ip

inner join 

(

select name from test_table 

where name = 'name'

) as c

on a.ip = c.name

where 

(a.time >= '2008-07-09 12:00:00') and 

(a. time <= '2008-07-10 13:00:00' )

order by a.time limit 200;


이렇게 하셔서 앞조건에서 일치하지않으면 스톱을 걸수 있게 해서 한번 해보시기 바랍니다.


이게 원하는 결과가 된다면


explain analyze

SELECT time, user, ip, name FROM test_table

WHERE

(   user = 'test') and

(   name = 'oldman') and

(   ip = 1023421 )and

(   time >= '2008-07-09 12:00:00' ) and 

(   time <= '2008-07-10 13:00:00' )

order by time limit 200;


쿼리를 이렇게 작성하셔서 해보시기 바랍니다.


일단 쿼리를 좀 수정해서 원하는 결과값이 나오는지 한번 explain한 결과값을 올려주시기 바랍니다.

김병석(byung82)님이 2008-07-29 18:27에 작성한 댓글입니다.



time 컬럼의 값과 다른 컬럼 하나의 값만 있을땐 빠르고 (user_idx, ip_idx, name_idx)
모든 컬럼의 조건값을 넣고 조회한 경우가 느리다면 (all_idx)
time 컬럼의 데이터 분포도의 문제이거나 해당 쿼리의 time 컬럼 조건의 카디널리티가 낮은것으로 보입니다.

all_idx 인덱스의 경우만 time컬럼이 앞쪽에 위치하죠..


time >= '2008-07-09 12:00:00' and 
time <= '2008-07-10 13:00:00' and

이조건만 주고 count해보세요. 아마 손익분기를 넘어서는 데이터량이 나올겁니다.

all_idx인덱스를 사용하는것이, 테이블 전체 스캔을 하거나 user_idx,ip_idx,name_idx중에 하나를 스킵스캔하는거보다 불리하다고 하면 all_idx인덱스를 사용하지 않는 실행계획이 나와야 하는데요..

아마 통계정보의 문제이거나 옵티마이저 설정값의 문제로 인해 제대로 판단을 못하는걸로 보입니다.

analyze 명령으로 해당 테이블의 통계정보를 업데이트 해주시고 다시 실행계획을 확인해보십시요.
time 컬럼의 데이터 분포도가 불량하다고 하면 all_idx 인덱스의 컬럼 순서를 조정해보세요.

백수환(back17)님이 2008-08-01 21:25에 작성한 댓글입니다.
이 댓글은 2008-08-01 21:28에 마지막으로 수정되었습니다.
[Top]
No.
제목
작성자
작성일
조회
7483레코드 ID로 복수테이블 생성 [6]
chunrima
2008-08-06
5889
7482테이블 컬럼을 변경했을시에 나는에러.
나윤성
2008-08-04
6307
7480증분 백업에 대해
레전드
2008-08-02
6726
7478인덱스 관련 질문(WHERE조건이 많을 경우)... [4]
오래된남자
2008-07-29
8326
7475count(*) 의 성능은? [4]
산하
2008-07-29
6999
7474날짜가 중복이 안되게 등록하려고 하는데요 [1]
만수
2008-07-28
7142
7473SELECT 시에 인덱스를 강제로 지정하는 방법이 있나요? [2]
오래된남자
2008-07-28
6943
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.020초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다