2015-01-09 2 views
0

안녕하세요 저는 IN 절이있는 쿼리가 있습니다. IN-List는 큰 verry 일 수 있으므로 먼저 임시 테이블을 생성하고 있지만 이는 내 쿼리 계획을 위반하고 오래 걸립니다. 임시 테이블없이 TEMPTABLE임시 테이블을 사용하여 쿼리 계획을 죽입니다

CREATE TEMPORARY TABLE tempcards (cardid bigint) ON COMMIT DROP; 
INSERT INTO tempcards (cardid) VALUES (204313100); 


EXPLAIN SELECT 
count(*) 
FROM filecardentity sourcecard 
INNER JOIN lessonentity ON (sourcelesson_lessonid = sourcecard.lesson_lessonid) 
INNER JOIN assignmentdelivery ON (assignmentdelivery.assignment_id = lessonentity.assignment_id) 
--LEFT JOIN filecardentity targetcard ON (targetcard.original_cardid = sourcecard.cardid AND targetcard.assignment_id = lessonentity.assignment_id) 
WHERE sourcecard.cardid IN (SELECT cardid FROM tempcards) 

"Aggregate (cost=2006601.72..2006601.73 rows=1 width=0)" 
" -> Merge Join (cost=949476.63..1820711.11 rows=74356243 width=0)" 
"  Merge Cond: (sourcecard.lesson_lessonid = lessonentity.sourcelesson_lessonid)" 
"  -> Sort (cost=673658.21..688573.90 rows=5966274 width=8)" 
"    Sort Key: sourcecard.lesson_lessonid" 
"    -> Nested Loop (cost=36.75..2201.84 rows=5966274 width=8)" 
"     -> HashAggregate (cost=36.75..38.75 rows=200 width=8)" 
"       -> Seq Scan on tempcards (cost=0.00..31.40 rows=2140 width=8)" 
"     -> Index Scan using filecardentity_pkey on filecardentity sourcecard (cost=0.00..10.81 rows=1 width=16)" 
"       Index Cond: (cardid = tempcards.cardid)" 
"  -> Sort (cost=275803.27..280152.44 rows=1739667 width=8)" 
"    Sort Key: lessonentity.sourcelesson_lessonid" 
"    -> Merge Join (cost=74428.81..95483.48 rows=1739667 width=8)" 
"     Merge Cond: (assignmentdelivery.assignment_id = lessonentity.assignment_id)" 
"     -> Index Only Scan using fk_fk11c5a601f3011b4_idx on assignmentdelivery (cost=0.00..1374.42 rows=51344 width=8)" 
"     -> Sort (cost=74402.44..75901.33 rows=599555 width=16)" 
"       Sort Key: lessonentity.assignment_id" 
"       -> Seq Scan on lessonentity (cost=0.00..16864.55 rows=599555 width=16)" 

=> 800ms

함께

EXPLAIN SELECT 
count(*) 
FROM filecardentity sourcecard 
INNER JOIN lessonentity ON (sourcelesson_lessonid = sourcecard.lesson_lessonid) 
INNER JOIN assignmentdelivery ON (assignmentdelivery.assignment_id = lessonentity.assignment_id) 
--LEFT JOIN filecardentity targetcard ON (targetcard.original_cardid = sourcecard.cardid AND targetcard.assignment_id = lessonentity.assignment_id) 
WHERE sourcecard.cardid IN (204313100) 

"Aggregate (cost=274.15..274.16 rows=1 width=0)" 
" -> Nested Loop (cost=0.00..274.12 rows=12 width=0)" 
"  -> Nested Loop (cost=0.00..263.02 rows=4 width=8)" 
"    -> Index Scan using filecardentity_pkey on filecardentity sourcecard (cost=0.00..10.87 rows=1 width=8)" 
"     Index Cond: (cardid = 204313100)" 
"    -> Index Scan using fk_fka046075b829910ba_idx on lessonentity (cost=0.00..251.42 rows=73 width=16)" 
"     Index Cond: (sourcelesson_lessonid = sourcecard.lesson_lessonid)" 
"  -> Index Only Scan using fk_fk11c5a601f3011b4_idx on assignmentdelivery (cost=0.00..2.77 rows=1 width=8)" 
"    Index Cond: (assignment_id = lessonentity.assignment_id)" 

=>은 CTE 및 EXISTS를 사용

+0

아직 시도하지 않았습니다 – wutzebaer

+2

'분석을하고'해당 계획을 게시 할 수 있습니까? –

+0

그러면 .. 다시 시도해 보니 도움이되었습니다 – wutzebaer

답변

1

예 55ms :

WITH input AS (
    -- the string '1,2,3,4' can be your input from the client 
    SELECT unnest(string_to_array('1,2,3,4', ',')::int[]) AS id -- just an example for the input 
) 
SELECT * 
FROM foo 
WHERE EXISTS(
    SELECT 42 -- just something 
    FROM input -- your cte or temp table if you don't use a cte at all 
    WHERE input.id = foo -- the "join" 
); 

임시 테이블을 계속 사용하려면 임시 테이블을 사용하도록 EXISTS를 변경하고 쿼리의 첫 번째 (WITH) 부분 만 삭제하십시오.

이 예제의 입력은 공백없이 쉼표로 구분 된 정수를 포함하는 문자열입니다.

관련 문제