चूंकि मैं एक युवा डेवलपर हूं और डेटाबेस (PostgreSQL 9.3) का उपयोग करने में वास्तव में कुशल नहीं हूं, इसलिए मैं एक परियोजना के साथ कुछ समस्याओं में भाग गया, जहां मुझे वास्तव में मदद की आवश्यकता है।
मेरी परियोजना उपकरणों (1000 या अधिक उपकरणों तक) से डेटा एकत्र करने के बारे में है, जहां हर डिवाइस प्रत्येक सेकंड में एक डेटा ब्लॉक भेज रहा है, जो प्रति घंटे लगभग 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, क्योंकि मेरे चुनिंदा बयान हमेशा समय के साथ क्वेरी करते हैं और अक्सर समय + मैक पर भी।
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 करने के लिए बड़ी तालिकाओं के साथ ऐसी समस्या को हल करने का एक सुंदर तरीका है?
मैं विभाजन के बारे में पढ़ता हूं, लेकिन यह मेरे डेटाए, डेटाबी, डेटासी संदर्भों के साथ काम नहीं करेगा data_block_id सही? अगर यह किसी तरह काम करेगा, तो क्या मुझे समय के साथ या मैक पर विभाजन करना चाहिए?
मैंने अपने सूचकांक को दूसरी दिशा में बदल दिया। पहले मैक, फिर टाइमस्टैम्प, और यह बहुत अधिक प्रदर्शन हासिल करता है।
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