ฉันพยายามที่จะกำหนดดัชนีที่จะใช้สำหรับแบบสอบถาม SQL ที่มีWHERE
เงื่อนไขและ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);
การใช้งานอธิบายในแบบสอบถามให้ผลลัพธ์ดังต่อไปนี้
"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
แผนแบบสอบถามสำหรับแบบสอบถาม LATERAL จาก ypercube:
"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
บนโต๊ะมีค่าต่างกันกี่ค่า?