उपयोग किए गए अरबों-पंक्तियों-तालिका // सूचकांक पर धीमी क्वेरी


10

चूंकि मैं एक युवा डेवलपर हूं और डेटाबेस (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

जवाबों:


1

यह मेरे एमएस एसक्यूएल पूर्वाग्रह को प्रतिबिंबित कर सकता है, लेकिन मैं इसके द्वारा तालिका को क्लस्टर करना चाहूंगा timestamp। यदि आप किसी विशिष्ट समय अवधि के लिए अक्सर डेटा खींच रहे हैं, तो इससे मदद मिलेगी क्योंकि डेटा भौतिक रूप से संचित रूप से संग्रहीत किया जाएगा। सिस्टम प्रारंभ बिंदु की तलाश कर सकता है, सीमा के अंत तक स्कैन कर सकता है, और किया जा सकता है। यदि आप किसी विशिष्ट घंटे के लिए क्वेरी कर रहे हैं, तो यह केवल 3,600,000 रिकॉर्ड है।

यदि आपकी क्वेरी (जो है ...?) एक विशिष्ट मशीन के लिए है, तो Postgres को उन 3.6 M रिकॉर्ड में से 99.9% फ़िल्टर करने की आवश्यकता होगी। यदि यह एक-इन-द-हज़ार फ़िल्टर किसी विशिष्ट दिनांक श्रेणी फ़िटर की तुलना में अधिक चयनात्मक है, तो आपको macअपने अनुक्रमणिका के पहले घटक के रूप में अधिक चयनात्मक फ़ील्ड का उपयोग करना चाहिए । यह अभी भी क्लस्टरिंग के लायक हो सकता है।

यदि वह अभी भी ऐसा नहीं करता है, तो मैं उसी क्षेत्र द्वारा विभाजन करूंगा, जिसे आप timestampया तो अनुक्रमणित कर रहे हैं mac

आपने डेटा प्रकार नहीं दिए। क्या वे डेटा के लिए उपयुक्त हैं? उदाहरण के लिए, पाठ को दिनांक के रूप में संग्रहीत करना अनावश्यक रूप से आपकी तालिका को धुंधला कर देगा।


2
पोस्टग्रेज में क्लस्टर इंडेक्स नहीं हैं (हालांकि यह एक इंडेक्स के साथ एक टेबल को क्लस्टर कर सकता है - लेकिन यह मैन्युअल रूप से किया जाना चाहिए और "रहना" नहीं होगा)
a_horse_with_no_name

सलाह के लिए आभार। अब यह पहले की तुलना में तेज़ी से चलता है, लेकिन फिर भी बहुत कम प्रदर्शन> प्रति प्रश्न 30 सेकंड। मैंने क्लस्टरिंग भी की, लेकिन जैसा कि @a_horse_with_no_name ने कहा: पोस्टग्रेज में यह एक-शॉट है। मेरे डेटा प्रकार सही हैं मुझे लगता है। मैंने उन्हें प्रश्न में जोड़ा
मानव

संकुल सारणी के बिना, रेंज प्रश्नों के लिए मेरी अगली सिफारिश विभाजन होगी।
जॉन ऑफ ऑल ट्रेड्स

-2

मैंने एक ऐसे अनुप्रयोग पर काम किया जिसमें बिजली के मीटर से अरबों रीडिंग थीं और 10 सेकंड के भीतर अधिकांश प्रश्नों को निष्पादित किया।

हमारा माहौल अलग था। Microsoft SQL Server सर्वर क्लास मशीन (4 कोर, 24 जीबी मेमोरी) पर। सर्वर पर अपग्रेड करने का कोई मौका?

एक बड़ा मुद्दा यह है कि एक समय में रीडिंग में प्रवेश करने से डेटाबेस पर बड़ा प्रदर्शन प्रभाव पड़ता है। डेटा लेखन ताले और प्रश्नों की आवश्यकता होगी। क्या आप बैचों में आवेषण कर सकते हैं?

अपने स्कीमा के साथ, आपके पास 4 बहुत बड़ी टेबल होंगी। यह महत्वपूर्ण होगा कि आपके सभी जोड़ दोनों तालिकाओं पर अनुक्रमित का उपयोग करें। एक टेबल स्कैन हमेशा के लिए ले जाएगा। क्या अशक्त सक्षम क्षेत्रों के साथ उन्हें 1 तालिका में विलय करना संभव है?


बैचों में आवेषण: मैं बल्क-इन्सर्ट कर सकता था, लेकिन फ़िलहाल एक परीक्षण डेटाबेस पर काम कर रहा था, जहाँ कोई क्वेरी चलते समय कोई आवेषण नहीं किया जाता है। लेकिन धन्यवाद मैं बाद में सोचूंगा :) सूचकांकों: मैं हर तालिकाओं पर अनुक्रमित करता हूं। डेटा पर आईडी पर एक इंडेक्स टेबल्स पर (मैक, टाइमस्टैम्प) डेटा_ब्लॉक टेबल पर। समस्या यह भी है जब im डेटाए के लिए खोज करता है प्रति बाएं-जुड़ो लेकिन चिकित्सा नहीं है। इंडेक्स के साथ भी यह डेटा टेबल को खोजता है। अशक्त क्षेत्र: संभव नहीं हैं क्योंकि डेटा_ब्लॉक में एक से अधिक डेटा हो सकते हैं। 1xdata_block -> 4xdataA जैसे
मैनमैन

क्या आपका DB टूल आपको क्वेरी विश्लेषक देता है? आपको id के आधार पर data_block पर एक इंडेक्स की आवश्यकता हो सकती है।
केसी-एनएच

मैं कोशिश करूँगा, लेकिन मुझे समझ में नहीं आता कि यह क्यों मदद कर सकता है !?
मैनमैन

-2

आप पोस्टग्रेज (या किसी अन्य RDBMS) की अंतर्निहित स्केलेबिलिटी सीमा को मार रहे हैं।

याद रखें कि RDBMS इंडेक्स एक बी-ट्री है। ए बी-ट्री औसत और सबसे खराब स्थिति दोनों के लिए ओ (लॉग एन) है। यह एन के उचित मूल्यों के लिए एक अच्छा, सुरक्षित, पूर्वानुमान योग्य विकल्प बनाता है। जब एन बहुत बड़ा हो जाता है तो यह टूट जाता है।

NoSQL डेटाबेस (अधिकांश भाग के लिए) हैश टेबल हैं। एक हैश तालिका औसत मामले में O (1) और सबसे खराब स्थिति में O (n) है। मान लें कि आप सबसे खराब स्थिति से बच सकते हैं, यह एन के बहुत बड़े मूल्यों के लिए वास्तव में अच्छा प्रदर्शन करता है।

इसके अतिरिक्त, एक हैश तालिका समानांतर करना आसान है और एक बी-ट्री नहीं है। यह हैश तालिकाओं को वितरित कंप्यूटिंग वास्तुकला के लिए अधिक उपयुक्त बनाता है।

जब आप बिलियन रो टेबल्स पर जाने लगते हैं, तो RDBMS से NoSQL पर स्विच करने पर विचार करने का समय है। कैसंड्रा शायद आपके उपयोग के मामले के लिए एक अच्छा विकल्प होगा।


2
RDBMS के बहुत से बी-ट्री इंडेक्स (हैश, बिटमैप और अन्य) की तुलना में कई अधिक विकल्प हैं। कुछ DBMS पंक्तियों को संग्रहीत कर रहे हैं और कुछ स्तंभों को संग्रहीत कर रहे हैं। और ओ (लोगन) अरबों पंक्तियों के लिए भी बुरा नहीं है। और वे संभवतः 4 जीबी मेमोरी मशीन का उपयोग करते समय किसी भी सीमा को नहीं मार सकते हैं।
ypercube y
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.