2011-11-25 11 views
5

मैं एक नया PostgreSQL 9 डेटाबेस स्थापित कर रहा हूं जिसमें लाखों (या शायद अरबों) पंक्तियां होंगी। तो मैंने PostgreSQL विरासत का उपयोग कर डेटा विभाजन करने का फैसला किया।सही विभाजन नियम का चयन

CREATE TABLE mytable 
(
    user_id integer, 
    year integer, 
    CONSTRAINT pk_mytable PRIMARY KEY (user_id, year) 
); 

और 10 पार्टीशन टेबल:

मैं इस तरह एक मास्टर तालिका (उदाहरण के लिए सरलीकृत) बनाया

CREATE TABLE mytable_0() INHERITS (mytable); 
CREATE TABLE mytable_1() INHERITS (mytable); 
... 
CREATE TABLE mytable_9() INHERITS (mytable); 

मुझे पता है कि पंक्तियों हमेशा एक अद्वितीय का उपयोग कर आवेदन से पहुँचा जा जाएगा user_id हालत। तो मैं user_id के आधार पर नियम का उपयोग करके 10 टेबलों पर समान रूप से "काफी" डेटा प्रसारित करना चाहता हूं।

मास्टर मेज पर धुन प्रश्नों के लिए

, मेरा पहला विचार एक मापांक जांच बाधा का इस्तेमाल किया गया:

ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 0); 
ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 1); 
... 

समस्या यह है, जब मैं user_id, PostgreSQL पर शर्त के साथ मास्टर तालिका "mytable" क्वेरी विश्लेषक सभी तालिकाओं की जाँच करें और जाँच बाधा से लाभ नहीं मिलता:

EXPLAIN SELECT * FROM mytable WHERE user_id = 12345; 

"Result (cost=0.00..152.69 rows=64 width=36)" 
" -> Append (cost=0.00..152.69 rows=64 width=36)" 
"  -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)" 
"    Filter: (user_id = 12345)" 
"  -> Seq Scan on mytable_0 mytable (cost=0.00..1.29 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 
"  -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 
... 
"  -> Seq Scan on mytable_9 mytable (cost=0.00..1.52 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 

जबकि यदि मैं (और पुनः विभाजन है कि उस नियम से मेल) इस तरह एक क्लासिक जाँच प्रतिबंध का उपयोग करें:

ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 1 AND 10000); 
ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 10001 AND 20000); 
... 

यह केवल तालिकाओं हालत (mytable और इस उदाहरण में mytable_1) से मेल स्कैन करेगा:

"Result (cost=0.00..152.69 rows=64 width=36)" 
" -> Append (cost=0.00..152.69 rows=64 width=36)" 
"  -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)" 
"    Filter: (user_id = 12345)" 
"  -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)" 
"    Filter: (user_id = 12345)" 

लेकिन इस तरह की जांच बाधा का उपयोग कर बनाए रखने के लिए कठिन है क्योंकि उन की सीमा है कि में से भरी हुई होगी वर्षों में टेबल बदल जाएगा। हजारों पहले, शायद निकट भविष्य में लाखों या उससे अधिक ...

10 टेबल पर मेरे डेटा को समान रूप से विभाजित करने के लिए मैं किस नियम का उपयोग कर सकता हूं जो चेक बाधा से लाभ उठा सकता है ताकि मास्टर टेबल पर एक चयन केवल स्कैन करेगा सही टेबल ...?

धन्यवाद, निको

उत्तर

5

सीमा योजनाकार बजाय partioning के साथ ही है। यह कुछ विस्तार में मैनुअल में शामिल है:

http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html

दो चीजें आप का उल्लेख हालांकि विचार किया जाना है कि जरूरत है।

सबसे पहले, आप कहते हैं कि सभी एक्सेस प्राथमिक कुंजी के माध्यम से होंगे। इसका मतलब है कि आपको विभाजन से कोई प्रदर्शन लाभ नहीं मिलेगा (कम से कम सामान्य उपयोग में नहीं)। प्रत्येक विभाजन पर सूचकांक छोटा होगा, लेकिन पीजी को पहले से जांचने के लिए कौन सा विभाजन चुनना होगा। आपको लाभ मिलेगा यदि आपको रीइंडेक्स या समान करने की आवश्यकता है - तो आप प्रत्येक विभाजन को अलग-अलग पुनर्निर्मित कर सकते हैं।

दूसरा, आप कहते हैं कि आपके पास हजारों से अरबों पंक्तियों में कुछ भी हो सकता है। यह मुझे दो निष्कर्षों तक ले जाता है:

  1. शायद बाद में निर्णय छोड़ दें। प्रतीक्षा करें जब तक आपको विभाजन करने की आवश्यकता न हो।
  2. आप दो हजार पंक्तियों और दो बिलियन के साथ बिल्कुल 10 विभाजन चाहते हैं।

यदि आप विभाजन करने जा रहे हैं, तो इसे सीमा से करें - 100,000 पंक्तियों या प्रति विभाजन 1 मिलियन कहें। इस्तेमाल की गई अधिकतम आईडी की जांच करने के लिए एक क्रॉन-जॉब जोड़ें और यदि आवश्यक हो तो एक नया विभाजन बनाएं (शायद एक दिन में)।

व्यक्तिगत रूप से, हालांकि, मैं इसे तब तक छोड़ दूंगा जब तक मुझे इसकी आवश्यकता न हो। हो सकता है कि कैच-सब के रूप में एक ही विभाजन हो, यदि आपको लगता है कि इससे पहले की आवश्यकता नहीं है तो आपको इसकी आवश्यकता होगी।

1

WHERECHECK के समान अभिव्यक्ति पर होना चाहिए, i। ई।, क्वेरी प्लानर को यह एहसास नहीं होगा कि user_id = 12345 निष्कर्ष निकालने की अनुमति देता है कि user_id % 10 = 5। प्रयास करें

EXPLAIN SELECT * FROM mytable WHERE user_id = 12345 AND user_id % 10 = 5; 

यही कहा, मैं चाहते हैं के बाद दूसरे स्थान में Richard Huxton's answer कि आप विभाजन को स्थगित करने का जब तक आप डेटा सेट के आकार के बारे में अधिक जानकारी नहीं है, वें eidea समय से पहले अनुकूलन बचने के लिए किया जा रहा है चाहते हो सकता है। पोस्टग्रेज़ बड़ी टेबल पर बहुत तेज़ हो सकते हैं, यह आपको विभाजन के बिना काफी दूर ले जाएगा।

संबंधित मुद्दे