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 7094 게시물 읽기
No. 7094
쿼리 조건절을 원하는 순서로 할수 없을까요?
작성자
채종대
작성일
2007-04-06 01:45
조회수
5,284

검색 순서를 제가 원하는 방향으로 가고 싶은데 그리 싶지가 않네요. 

방법이 없을까요?


다음에 두가지 쿼리가 있습니다.

explain select a.accountnid, a.accountsid, a.charnid, a.charsid, scharnid, tcharnid, tcharacter.charsid, date_info

from

 ((select account.accountnid, account.accountsid, character.charnid, character.charsid

 from account, character

 where charsid = 'I천둥I' and account.accountnid = character.accountnid) as character

 join itemlog on

  character.charnid = itemlog.scharnid or character.charnid = itemlog.tcharnid) as a

 join action on

  a.actionid = action.actionid

 left join character as tcharacter

   on tcharacter.charnid = a.tcharnid

where date_info between 70330000000 and 70331000000


explain select a.accountnid, a.accountsid, a.charnid, a.charsid, scharnid, tcharnid, tcharacter.charsid, date_info

from

 ((select account.accountnid, account.accountsid, character.charnid, character.charsid

 from account, character

 where charsid = 'I천둥I' and account.accountnid = character.accountnid) as character

 join itemlog on

  character.charnid = itemlog.scharnid or character.charnid = itemlog.tcharnid) as a

 join action on

  a.actionid = action.actionid

 left join character as tcharacter

   on tcharacter.charnid = a.tcharnid


두 쿼리의 차이는 마지막 where 절인데요.

첫번째 쿼리의 explain은 

"Nested Loop Left Join  (cost=121591.61..370236.15 rows=252 width=282)"

"  ->  Nested Loop  (cost=121591.61..368563.05 rows=252 width=184)"

"        Join Filter: ((public."character".charnid = itemlog.scharnid) OR (public."character".charnid = itemlog.tcharnid))"

"        ->  Hash Join  (cost=120088.71..303553.87 rows=25151 width=16)"

"              Hash Cond: (itemlog.actionid = "action".actionid)"

"              ->  Seq Scan on itemlog  (cost=0.00..92663.17 rows=5030317 width=16)"

"              ->  Hash  (cost=119586.38..119586.38 rows=27307 width=16)"

"                    ->  Seq Scan on "action"  (cost=0.00..119586.38 rows=27307 width=16)"

"                          Filter: ((date_info >= 70330000000::bigint) AND (date_info <= 70331000000::bigint))"

"        ->  Materialize  (cost=1502.90..1503.91 rows=101 width=168)"

"              ->  Hash Join  (cost=991.11..1502.80 rows=101 width=168)"

"                    Hash Cond: (account.accountnid = public."character".accountnid)"

"                    ->  Seq Scan on account  (cost=0.00..276.87 rows=15587 width=66)"

"                    ->  Hash  (cost=989.85..989.85 rows=101 width=110)"

"                          ->  Seq Scan on "character"  (cost=0.00..989.85 rows=101 width=110)"

"                                Filter: ((charsid)::text = 'I천둥I'::text)"

"  ->  Index Scan using pk_user on "character" tcharacter  (cost=0.00..6.63 rows=1 width=102)"

"        Index Cond: (tcharacter.charnid = itemlog.tcharnid)"


두번째 쿼리의 explain은

"Hash Left Join  (cost=194940.70..4728172.47 rows=50432 width=282)"

"  Hash Cond: (itemlog.tcharnid = tcharacter.charnid)"

"  ->  Hash Join  (cost=193414.37..4722705.54 rows=50432 width=184)"

"        Hash Cond: (itemlog.actionid = "action".actionid)"

"        ->  Nested Loop  (cost=866.31..4494550.88 rows=50432 width=184)"

"              ->  Nested Loop  (cost=0.00..1678.37 rows=101 width=168)"

"                    ->  Seq Scan on "character"  (cost=0.00..989.85 rows=101 width=110)"

"                          Filter: ((charsid)::text = 'I천둥I'::text)"

"                    ->  Index Scan using pk_account on account  (cost=0.00..6.80 rows=1 width=66)"

"                          Index Cond: (account.accountnid = public."character".accountnid)"

"              ->  Bitmap Heap Scan on itemlog  (cost=866.31..43729.34 rows=50303 width=16)"

"                    Recheck Cond: ((public."character".charnid = itemlog.scharnid) OR (public."character".charnid = itemlog.tcharnid))"

"                    ->  BitmapOr  (cost=866.31..866.31 rows=50303 width=0)"

"                          ->  Bitmap Index Scan on idx_itemlog_scharnid  (cost=0.00..426.87 rows=25152 width=0)"

"                                Index Cond: (public."character".charnid = itemlog.scharnid)"

"                          ->  Bitmap Index Scan on idx_itemlog_tcharnid  (cost=0.00..426.87 rows=25152 width=0)"

"                                Index Cond: (public."character".charnid = itemlog.tcharnid)"

"        ->  Hash  (cost=92279.25..92279.25 rows=5461425 width=16)"

"              ->  Seq Scan on "action"  (cost=0.00..92279.25 rows=5461425 width=16)"

"  ->  Hash  (cost=939.48..939.48 rows=20148 width=102)"

"        ->  Seq Scan on "character" tcharacter  (cost=0.00..939.48 rows=20148 width=102)"


이렇게 나옵니다. where 조건절은 특정 시간을 표시하는거지만 동일 시간대에 많은 데이터가 쌓이기 때문에 첫번째 explain은 옳바른 방법이 아니라고 생각합니다.


그래서 첫번째 쿼리와 같은 결과를 유도하면서 두번째 explain을 나오게 하고 싶습니다.

temp 테이블을 써서 where 조건절만 나중에 할까도 생각했지만 썩 좋은 방법 같지는 않아서요.

쿼리 한번으로 해결할수 있는 좋은 방법이 없을까요?


select * from (...) as a where date_info between 70330000000 and 70331000000 

이렇게도 해보고 join도 써보고 별 방법을 다 써봤지만 날짜 조건이 들어가면 그것부터 검색하게 되네요.

어떻게 하면 좋을까요? 


좋은 정보를 주시면 감사하겠습니다. 부탁드립니다.

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

결국 꽁수를 썼네요. 쿼리 우선순위를 정할수 있는 방법이나 뭔가 다른 수단이 있으면 꼭 좀 가르쳐 주세요.


 FOR _RetRow IN
  select accountsid, scharacter.charsid, tcharacter.charsid as tcharsid, action_type, itemnid, itemserial, count, revivalcount, date_info
  from account, character, action, itemlog
   left join character as tcharacter
   on tcharacter.charnid = itemlog.tcharnid
   join character as scharacter
   on scharacter.charnid = itemlog.scharnid
  where character.charsid = _szCharSID and account.accountnid = character.accountnid and
   (character.charnid = itemlog.scharnid or character.charnid = itemlog.tcharnid)
   and itemlog.actionid = action.actionid
  order by date_info
 LOOP
  IF (_RetRow.date_info >= _lldStartDate and _RetRow.date_info <= _lldEndDate) then
   RETURN NEXT _RetRow;
  END IF;
 END LOOP;

채종대님이 2007-04-06 10:05에 작성한 댓글입니다. Edit

subselect를 하는 inline view 를 사용하게 되면, 
그 뒷 결과로 만들어진 것에 대해서 join이 이루워지기 때문에, 
그 다음 작업에 대한 인덱스를 사용할 수 없게됩니다. 

자료가 어떤지는 모르겠지만, 

from 다음에 () 형태의 inline view 대신에 그냥 테이블로 하고, 
모두 합쳤는 쿼리를 만들어보세요. 

select * from account, character, itemlog, action where carsid = '...' .... 어쩌고 저쩌고..

이게 불가능하다면, 

select .... from .... where ... in ( select ....)

형태로 where 절 다음에 subselect를 사용해보든지요. 

답은 직접 찾으셔야겠네요.

아니면 윗 스스로 찾았는 방법처럼 set return 함수도 괜찮을 것같고요.

그런데, 반드시 left (inner) join을 써야하는 경우인가보죠?

김상기(ioseph)님이 2007-04-06 16:00에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
7098postgresql 에서 postgis 설치 할때요 ~ [1]
김현덕
2007-04-09
5184
7097PostgreSQL서버가 Win용과 Linux용일경우 속도 차이가 있나요? [1]
포스트
2007-04-07
5297
7095김상기님 copy문이 아직 [3]
김승일
2007-04-06
5897
7094쿼리 조건절을 원하는 순서로 할수 없을까요? [2]
채종대
2007-04-06
5284
7093postgres 사용자의 아이디와 비번 [1]
김근식
2007-04-05
9260
7092[도움요청]튜닝. Trace, 모니터링 방법 알려주세요. [1]
사이베이스가 싫어
2007-04-04
4959
7091게시판 count 어떻게 하시나요?? [4]
counter
2007-04-03
5383
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.022초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다