WHERE
조건이 있는 SQL 쿼리에 사용할 인덱스와 GROUP BY
현재 매우 느린 인덱스를 확인하려고합니다 .
내 쿼리 :
SELECT group_id
FROM counter
WHERE ts between timestamp '2014-03-02 00:00:00.0' and timestamp '2014-03-05 12:00:00.0'
GROUP BY group_id
테이블에는 현재 32.000.000 개의 행이 있습니다. 시간 프레임을 늘리면 쿼리 실행 시간이 많이 증가합니다.
해당 테이블은 다음과 같습니다.
CREATE TABLE counter (
id bigserial PRIMARY KEY
, ts timestamp NOT NULL
, group_id bigint NOT NULL
);
현재 다음 색인이 있지만 성능은 여전히 느립니다.
CREATE INDEX ts_index
ON counter
USING btree
(ts);
CREATE INDEX group_id_index
ON counter
USING btree
(group_id);
CREATE INDEX comp_1_index
ON counter
USING btree
(ts, group_id);
CREATE INDEX comp_2_index
ON counter
USING btree
(group_id, ts);
쿼리에서 EXPLAIN을 실행하면 다음과 같은 결과가 나타납니다.
"QUERY PLAN"
"HashAggregate (cost=467958.16..467958.17 rows=1 width=4)"
" -> Index Scan using ts_index on counter (cost=0.56..467470.93 rows=194892 width=4)"
" Index Cond: ((ts >= '2014-02-26 00:00:00'::timestamp without time zone) AND (ts <= '2014-02-27 23:59:00'::timestamp without time zone))"
예제 데이터가 포함 된 SQL Fiddle : http://sqlfiddle.com/#!15/7492b/1
질문
더 나은 인덱스를 추가하여이 쿼리의 성능을 향상시킬 수 있습니까, 아니면 처리 능력을 높여야합니까?
편집 1
PostgreSQL 버전 9.3.2가 사용됩니다.
편집 2
@Erwin의 제안을 EXISTS
다음 과 같이 시도했습니다 .
SELECT group_id
FROM groups g
WHERE EXISTS (
SELECT 1
FROM counter c
WHERE c.group_id = g.group_id
AND ts BETWEEN timestamp '2014-03-02 00:00:00'
AND timestamp '2014-03-05 12:00:00'
);
그러나 불행히도 이것은 성능을 향상 시키지는 못했습니다. 쿼리 계획 :
"QUERY PLAN"
"Nested Loop Semi Join (cost=1607.18..371680.60 rows=113 width=4)"
" -> Seq Scan on groups g (cost=0.00..2.33 rows=133 width=4)"
" -> Bitmap Heap Scan on counter c (cost=1607.18..158895.53 rows=60641 width=4)"
" Recheck Cond: ((group_id = g.id) AND (ts >= '2014-01-01 00:00:00'::timestamp without time zone) AND (ts <= '2014-03-05 12:00:00'::timestamp without time zone))"
" -> Bitmap Index Scan on comp_2_index (cost=0.00..1592.02 rows=60641 width=0)"
" Index Cond: ((group_id = g.id) AND (ts >= '2014-01-01 00:00:00'::timestamp without time zone) AND (ts <= '2014-03-05 12:00:00'::timestamp without time zone))"
편집 3
ypercube의 LATERAL 쿼리에 대한 쿼리 계획 :
"QUERY PLAN"
"Nested Loop (cost=8.98..1200.42 rows=133 width=20)"
" -> Seq Scan on groups g (cost=0.00..2.33 rows=133 width=4)"
" -> Result (cost=8.98..8.99 rows=1 width=0)"
" One-Time Filter: ($1 IS NOT NULL)"
" InitPlan 1 (returns $1)"
" -> Limit (cost=0.56..4.49 rows=1 width=8)"
" -> Index Only Scan using comp_2_index on counter c (cost=0.56..1098691.21 rows=279808 width=8)"
" Index Cond: ((group_id = $0) AND (ts IS NOT NULL) AND (ts >= '2010-03-02 00:00:00'::timestamp without time zone) AND (ts <= '2014-03-05 12:00:00'::timestamp without time zone))"
" InitPlan 2 (returns $2)"
" -> Limit (cost=0.56..4.49 rows=1 width=8)"
" -> Index Only Scan Backward using comp_2_index on counter c_1 (cost=0.56..1098691.21 rows=279808 width=8)"
" Index Cond: ((group_id = $0) AND (ts IS NOT NULL) AND (ts >= '2010-03-02 00:00:00'::timestamp without time zone) AND (ts <= '2014-03-05 12:00:00'::timestamp without time zone))"
group_id
있고 어떤 것도 아닌가?
group_id
테이블에 몇 개의 다른 값이 있습니까?