เนื่องจากฉันเป็นนักพัฒนาอายุน้อยและไม่ชำนาญในการใช้ฐานข้อมูล (PostgreSQL 9.3) ฉันพบปัญหาบางอย่างเกี่ยวกับโครงการที่ฉันต้องการความช่วยเหลือ
โครงการของฉันเกี่ยวกับการรวบรวมข้อมูลจากอุปกรณ์ (มากถึง 1,000 อุปกรณ์ขึ้นไป) ซึ่งทุกอุปกรณ์กำลังส่งข้อมูลหนึ่งบล็อกทุกวินาทีซึ่งจะสร้างประมาณ 3 ล้านแถวต่อชั่วโมง
ขณะนี้ฉันมีตารางขนาดใหญ่หนึ่งตารางที่ฉันเก็บข้อมูลขาเข้าของทุกอุปกรณ์:
CREATE TABLE data_block(
id bigserial
timestamp timestamp
mac bigint
)
เนื่องจากมีข้อมูลหลายประเภทที่บล็อกข้อมูลสามารถ (หรือไม่สามารถ) รวมจึงมีตารางอื่น ๆ ที่อ้างอิงdata_block
ตาราง
CREATE TABLE dataA(
data_block_id bigserial
data
CONSTRAINT fkey FOREIGN KEY (data_block_id) REFERENCES data_block(id);
);
CREATE TABLE dataB(...);
CREATE TABLE dataC(...);
CREATE INDEX index_dataA_block_id ON dataA (data_block_id DESC);
...
เป็นไปได้ว่าใน data_block เดียวมี 3x dataA, 1x dataB แต่ไม่มี dataC
ข้อมูลจะถูกเก็บไว้เป็นเวลาหลายสัปดาห์ดังนั้นฉันจะมีแถวประมาณ 5 พันล้านแถวในตารางนี้ ในขณะนี้ฉันมีตารางประมาณ 600 ล้านแถวและข้อความค้นหาของฉันใช้เวลานานมาก ดังนั้นฉันตัดสินใจที่จะทำดัชนีมากกว่าtimestamp
และmac
เพราะคำสั่งที่เลือกของฉันมักจะค้นหาตลอดเวลาและบ่อยครั้งที่เวลา + mac
CREATE INDEX index_ts_mac ON data_block (timestamp DESC, mac);
... แต่ข้อความค้นหาของฉันยังคงใช้เวลานาน ตัวอย่างเช่นฉันสอบถามข้อมูลสำหรับหนึ่งวันและหนึ่งวัน:
SELECT * FROM data_block
WHERE timestamp>'2014-09-15'
AND timestamp<'2014-09-17'
AND mac=123456789
Index Scan using index_ts_mac on data_block (cost=0.57..957307.24 rows=315409 width=32) (actual time=39.849..334534.972 rows=285857 loops=1)
Index Cond: ((timestamp > '2014-09-14 00:00:00'::timestamp without time zone) AND (timestamp < '2014-09-16 00:00:00'::timestamp without time zone) AND (mac = 123456789))
Total runtime: 334642.078 ms
ฉันทำสุญญากาศเต็มก่อนที่จะเรียกใช้คิวรี มีวิธีหรูหราในการแก้ปัญหาดังกล่าวกับตารางใหญ่ทำแบบสอบถาม <10sec?
ฉันอ่านเกี่ยวกับการแบ่งพาร์ติชัน แต่จะไม่สามารถใช้ได้กับ dataA, dataB, dataC ของฉันที่อ้างอิงถึง data_block_id ใช่มั้ย หากใช้งานได้ฉันควรแบ่งพาร์ติชั่นตามช่วงเวลาหรือบน mac
ฉันเปลี่ยนดัชนีเป็นทิศทางอื่น MAC เครื่องแรกจากนั้นประทับเวลาและเพิ่มประสิทธิภาพได้มาก
CREATE INDEX index_mac_ts ON data_block (mac, timestamp DESC);
แต่ก็ยังมีการสืบค้นใช้เวลา> 30 วินาที โดยเฉพาะอย่างยิ่งเมื่อฉันทำLEFT JOIN
กับตารางข้อมูลของฉัน นี่คือEXPLAIN ANALYZE
แบบสอบถามที่มีดัชนีใหม่:
EXPLAIN ANALYZE SELECT * FROM data_block WHERE mac = 123456789 AND timestamp < '2014-10-05 00:00:00' AND timestamp > '2014-10-04 00:00:00'
Bitmap Heap Scan on data_block (cost=1514.57..89137.07 rows=58667 width=28) (actual time=2420.842..32353.678 rows=51342 loops=1)
Recheck Cond: ((mac = 123456789) AND (timestamp < '2014-10-05 00:00:00'::timestamp without time zone) AND (timestamp > '2014-10-04 00:00:00'::timestamp without time zone))
-> Bitmap Index Scan on index_mac_ts (cost=0.00..1499.90 rows=58667 width=0) (actual time=2399.291..2399.291 rows=51342 loops=1)
Index Cond: ((mac = 123456789) AND (timestamp < '2014-10-05 00:00:00'::timestamp without time zone) AND (timestamp > '2014-10-04 00:00:00'::timestamp without time zone))
Total runtime: 32360.620 ms
น่าเสียดายที่ฮาร์ดแวร์ของฉันถูก จำกัด อย่างเข้มงวด ฉันใช้ Intel i3-2100 @ 3.10Ghz, 4GB RAM การตั้งค่าปัจจุบันของฉันมีดังนี้:
default_statistics_target = 100
maintenance_work_mem = 512MB
constraint_exclusion = on
checkpoint_completion_target = 0.9
effective_cache_size = 4GB
work_mem = 512MB
wal_buffers = 16MB
checkpoint_segments = 32
shared_buffers = 2GB
max_connections = 20
random_page_cost = 2