प्रभावी mysql तालिका / अनुक्रमणिका डिज़ाइन 35 मिलियन पंक्तियों + तालिका के लिए, 200+ संगत स्तंभों (डबल) के साथ, जिनमें से किसी भी संयोजन को क्वेरी किया जा सकता है


17

मैं निम्नलिखित स्थिति के लिए तालिका / सूचकांक डिजाइन पर सलाह की तलाश कर रहा हूं:

मेरे पास एक कंपाउंड प्राइमरी कुंजी (एसेटिड (इंट), डेट (तारीख)) के साथ एक बड़ी टेबल (स्टॉक प्राइस हिस्ट्री डेटा, इनोबीडी, 35 मिलियन पंक्तियाँ और बढ़ती) हैं। मूल्य निर्धारण की जानकारी के अलावा, मेरे पास 200 दोहरे मूल्य हैं जो प्रत्येक रिकॉर्ड के अनुरूप होने की आवश्यकता है।

CREATE TABLE `mytable` (
`assetid` int(11) NOT NULL,
`date` date NOT NULL,
`close` double NOT NULL,
`f1` double DEFAULT NULL,   
`f2` double DEFAULT NULL,
`f3` double DEFAULT NULL,   
`f4` double DEFAULT NULL,
 ... skip a few 
`f200` double DEFAULT NULL, 
PRIMARY KEY (`assetid`, `date`)) ENGINE=`InnoDB` DEFAULT CHARACTER SET latin1 COLLATE
    latin1_swedish_ci ROW_FORMAT=COMPACT CHECKSUM=0 DELAY_KEY_WRITE=0 
    PARTITION BY RANGE COLUMNS(`date`) PARTITIONS 51;

मैंने शुरू में अद्यतन और पुनर्प्राप्ति में आसानी के लिए सीधे इस तालिका में 200 डबल कॉलम संग्रहीत किए, और यह ठीक काम कर रहा था, क्योंकि इस तालिका पर केवल क्वेरीज़ एसेटिड और तारीख द्वारा की गई थी (ये धार्मिक रूप से इस तालिका के खिलाफ किसी भी क्वेरी में शामिल हैं) ), और 200 डबल कॉलम केवल पढ़े गए थे। मेरे डेटाबेस का आकार 45 गिग के आसपास था

हालाँकि, अब मेरे पास वह आवश्यकता है जहां मुझे इन 200 कॉलमों के किसी भी संयोजन (उदाहरण के लिए f1, f2, ... f200) के द्वारा इस तालिका को क्वेरी करने में सक्षम होना चाहिए, उदाहरण के लिए:

select from mytable 
where assetid in (1,2,3,4,5,6,7,....)
and date > '2010-1-1' and date < '2013-4-5'
and f1 > -0.23 and f1 < 0.9
and f117 > 0.012 and f117 < .877
etc,etc

मुझे ऐतिहासिक रूप से इससे पहले डेटा की इस बड़ी मात्रा से निपटना नहीं पड़ा है, इसलिए मेरी पहली वृत्ति यह थी कि इन 200 स्तंभों में से प्रत्येक पर अनुक्रमित की आवश्यकता थी, या मैं बड़ी तालिका स्कैन आदि के साथ हवा करूंगा, मेरे लिए इसका मतलब यह था कि मुझे प्राथमिक कुंजी, मूल्य और मानों को अनुक्रमित करने वाले 200 स्तंभों में से प्रत्येक के लिए एक तालिका की आवश्यकता है। तो मैं उस के साथ चला गया।

CREATE TABLE `f1` (
`assetid` int(11) NOT NULL DEFAULT '0',
`date` date NOT NULL DEFAULT '0000-00-00',
`value` double NOT NULL DEFAULT '0',
PRIMARY KEY (`assetid`, `date`),
INDEX `val` (`value`)
) ENGINE=`InnoDB` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ROW_FORMAT=COMPACT CHECKSUM=0 DELAY_KEY_WRITE=0;

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

select count(p.assetid) as total 
from mytable p 
inner join f1 f1 on f1.assetid = p.assetid and f1.date = p.date
inner join f2 f2 on f2.assetid = p.assetid and f2.date = p.date 
where p.assetid in(1,2,3,4,5,6,7)
and p.date >= '2011-01-01' and p.date < '2013-03-14' 
and(f1.value >= 0.96 and f1.value <= 0.97 and f2.value >= 0.96 and f2.value <= 0.97) 

वास्तव में मेरा वांछित परिणाम प्राप्त किया गया था, मुझे समझाता है कि स्कैन की गई पंक्तियाँ इस क्वेरी के लिए बहुत छोटी हैं। हालांकि मैं कुछ अवांछनीय दुष्प्रभावों के साथ घायल हो गया।

1) मेरा डेटाबेस 45 गिग से 110 गिग तक चला गया। मैं अब db को RAM में नहीं रख सकता। (हालांकि मेरे पास रास्ते में 256Gig RAM है)

2) नए डेटा के रात के आवेषण को अब एक बार के बजाय 200 बार करने की आवश्यकता है

3) नई 200 टेबलों का रखरखाव / डीफ़्रैग केवल 1 टेबल की तुलना में 200 गुना अधिक समय लेता है। इसे एक रात में पूरा नहीं किया जा सकता है।

4) एफ 1 आदि के खिलाफ पूछताछ जरूरी नहीं है। उदाहरण के लिए:

 select min(value) from f1 
 where assetid in (1,2,3,4,5,6,7) 
 and date >= '2013-3-18' and date < '2013-3-19'

उपरोक्त क्वेरी, जबकि यह बताती है कि यह <1000 पंक्तियों में दिखता है, इसे पूरा करने में 30+ सेकंड लग सकते हैं। मुझे लगता है कि यह इसलिए है क्योंकि सूचकांक स्मृति में फिट होने के लिए बहुत बड़े हैं।

चूंकि यह बुरी खबर थी, इसलिए मैंने आगे देखा और विभाजन पाया। मैंने मुख्य सारणी पर विभाजन को लागू किया, हर 3 महीने में तारीख पर विभाजन। मासिक मुझे समझ में आ रहा था लेकिन मैंने पढ़ा है कि एक बार जब आप 120 से अधिक विभाजन प्राप्त करते हैं, तो प्रदर्शन में कमी आती है। अगले 20 वर्षों के लिए त्रैमासिक विभाजन मुझे उसी के तहत छोड़ देगा। प्रत्येक विभाजन 2 गिग के तहत एक सा है। मैं विभाजनों की व्याख्या करता था और सब कुछ ठीक से लगता था, इसलिए मुझे लगता है कि विभाजन एक अच्छा कदम था, विश्लेषण / अनुकूलन / मरम्मत के लिए बहुत कम से कम।

मैंने इस लेख के साथ अच्छा समय बिताया

http://ftp.nchu.edu.tw/MySQL/tech-resources/articles/testing-partitions-large-db.html

मेरी तालिका वर्तमान में अभी भी उस पर प्राथमिक कुंजी के साथ विभाजित है। लेख में उल्लेख किया गया है कि प्राथमिक कुंजियाँ एक विभाजित तालिका को धीमा कर सकती हैं, लेकिन यदि आपके पास एक मशीन है जो इसे संभाल सकती है, तो विभाजन तालिका में प्राथमिक कुंजियाँ तेज़ होंगी। यह जानकर कि मेरे पास रास्ते में एक बड़ी मशीन है (256 G RAM), मैंने चाबी छोड़ दी।

इसलिए जैसा कि मैंने इसे देखा, यहाँ मेरे विकल्प हैं

विकल्प 1

1) अतिरिक्त 200 तालिकाओं को हटा दें और f1, f2 आदि मानों को खोजने के लिए क्वेरी को टेबल स्कैन करने दें। गैर-अनूठे सूचकांक वास्तव में एक ठीक से विभाजित तालिका पर प्रदर्शन को चोट पहुंचा सकते हैं। उपयोगकर्ता द्वारा क्वेरी चलाने से पहले एक व्याख्या चलाएं और उन्हें स्कैन करें यदि स्कैन की गई पंक्तियों की संख्या कुछ सीमा से अधिक है जो मैं परिभाषित करता हूं। विशाल डेटाबेस के दर्द से खुद को बचाएं। बिल्ली, यह सब जल्द ही वैसे भी स्मृति में होगा।

उप प्रश्न:

क्या ऐसा लगता है कि मैंने एक उपयुक्त विभाजन योजना को चुना है?

विकल्प 2

एक ही 3 महीने की योजना का उपयोग करके सभी 200 तालिकाओं का विभाजन। छोटी पंक्ति स्कैन का आनंद लें और उपयोगकर्ताओं को बड़ी क्वेरी चलाने की अनुमति दें। अब जब वे कम से कम विभाजित होते हैं, तो मैं रखरखाव प्रयोजनों के लिए एक समय में उन्हें 1 विभाजन का प्रबंधन कर सकता हूं। बिल्ली, यह सब जल्द ही वैसे भी स्मृति में होगा। उन्हें रात में अद्यतन करने के लिए कुशल तरीका विकसित करें।

उप प्रश्न:

क्या आप एक कारण देखते हैं कि मैं इन एफ 1, एफ 2, एफ 3, एफ 4 ... टेबल पर प्राथमिक कुंजी अनुक्रमों से बच सकता हूं, यह जानते हुए कि क्वेरी करते समय मेरे पास हमेशा संपत्ति और तारीख होती है? मेरे लिए काउंटर सहज लगता है, लेकिन मैं इस आकार के डेटा सेट के लिए उपयोग नहीं किया जाता हूं। कि डेटाबेस एक गुच्छा मुझे लगता है हटना होगा

विकल्प 3

उस स्थान को पुनः प्राप्त करने के लिए मास्टर तालिका में f1, f2, f3 कॉलम छोड़ें। अगर मैं 200 विशेषताओं को पढ़ने की आवश्यकता है, तो 200 जुड़ता है, शायद यह उतना धीमा नहीं होगा जितना लगता है।

विकल्प 4

मैंने अब तक जितना सोचा है, आप सभी के पास इसे तैयार करने का बेहतर तरीका है।

* नोट: मैं जल्द ही प्रत्येक आइटम में इन दोहरे मूल्यों में से एक और 50-100 जोड़ रहा हूं, इसलिए मुझे यह जानने की आवश्यकता है कि आने वाला डिजाइन क्या है।

किसी भी और सभी तरह की मदद के लिए धन्यवाद

अपडेट # 1 - 3/24/2013

मैं नीचे दिए गए टिप्पणियों में सुझाए गए विचार के साथ गया और निम्न सेटअप के साथ एक नई तालिका बनाई:

create table 'features'{
  assetid int,
  date    date,
  feature varchar(4),
  value   double
}

मैंने 3 महीने के अंतराल में तालिका का विभाजन किया।

मैंने पहले की 200 टेबलों को उड़ा दिया ताकि मेरा डेटाबेस 45 गिग पर वापस आ जाए और इस नई तालिका को भरना शुरू कर दिया। डेढ़ दिन बाद, यह पूरा हो गया, और मेरा डेटाबेस अब एक चब्बी २२० गिग्स पर बैठता है !

यह मास्टर टेबल से इन 200 मूल्यों को हटाने की संभावना को अनुमति देता है, जैसा कि मैं उन्हें एक में शामिल होने से प्राप्त कर सकता हूं, लेकिन यह वास्तव में मुझे केवल 25 गिग्स वापस दे देगा या शायद

मैंने इसे एसेटिड, प्राइमरी, फ़ीचर और मूल्य पर एक इंडेक्स पर एक प्राथमिक कुंजी बनाने के लिए कहा था, और 9 घंटे की चुगली के बाद वास्तव में यह एक दाँत नहीं बना था और ऐसा लग रहा था कि मैंने उस हिस्से को मार दिया।

मैंने कुछ विभाजनों का पुनर्निर्माण किया, लेकिन यह बहुत अधिक / किसी भी स्थान को पुनः प्राप्त करने के लिए प्रतीत नहीं हुआ।

तो यह समाधान ऐसा लगता है कि यह आदर्श नहीं है। क्या पंक्तियों में मुझे आश्चर्यचकित करने वाले स्तंभों की तुलना में बहुत अधिक जगह मिलती है, क्या ऐसा हो सकता है कि इस समाधान ने इतना अधिक स्थान लिया हो?

मुझे यह लेख आया:

http://www.chrismoos.com/2010/01/31/mysql-partitioning-tables-with-millions-of-rows

इसने मुझे एक विचार दिया। इसे कहते हैं:

सबसे पहले, मैंने तिथि के हिसाब से RANGE विभाजन के बारे में सोचा, और जब मैं अपने प्रश्नों में तिथि का उपयोग कर रहा हूं, तो क्वेरी के लिए बहुत बड़ी तिथि सीमा होना बहुत आम है, और इसका मतलब है कि यह आसानी से सभी विभाजनों को पूरा कर सकता है।

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

तो फिर, मैं एसेटिड और डेट वैसे भी प्राथमिक रूप से बंद हूं, इसलिए शायद इससे बहुत मदद नहीं मिलेगी।

किसी भी अधिक विचार / टिप्पणी की सराहना की जाएगी।


2
मैं यह देखने में विफल हूं कि आपको 200 तालिकाओं की आवश्यकता क्यों है। के साथ एक एकल तालिका (value_name varchar(20), value double)दुकान सब कुछ करने में सक्षम होगा ( value_nameकिया जा रहा है f1, f2, ...)
a_horse_with_no_name

धन्यवाद। कारण मैं उन्हें व्यक्तिगत रूप से एक मेज पर 50 अनुक्रमित की सीमा के द्वारा प्राप्त किया गया था। मैंने उन्हें 5 तालिकाओं में रखने के बारे में सोचा था, जिनमें से प्रत्येक में 40 मान हैं, लेकिन मैं प्रत्येक के लिए एक दिन में 17000 या तो रिकॉर्ड कर रहा हूं और यह नहीं जानता कि 40 अनुक्रमित वाली तालिका में क्या सम्मिलित प्रदर्शन होगा। ध्यान दें कि एसेटिड, तिथि के प्रत्येक संयोजन को एफ 1, एफ 2 ... मान मिलता है। क्या आप प्राथमिक कुंजी एसेटिड, दिनांक, शायद इंडेक्स ऑन (value_name, वैल्यू) के साथ एकल तालिका (एसेटिड, डेट, value_name, वैल्यू) के साथ सुझाव दे रहे हैं? उस तालिका में ३५ मिल * २०० = would बिलियन पंक्तियाँ होंगी लेकिन शायद विभाजन अच्छी तरह से काम करेगा?
डाइरनियर

साथ अपने अनुभवों को इस विधि की कोशिश कर अपडेट किया गया पोस्ट
dyeryn

मेरे पास विकास का अंतिम समाधान है, जब मैं समाप्त कर लूंगा, तब अपडेट करूंगा। यह अनिवार्य रूप से विशिष्ट विभाजन और तार्किक तीक्ष्णता के साथ प्रस्तावित एकल तालिका समाधान है।
15

एक अलग भंडारण इंजन की मदद हो सकती है? InnoDb के बजाय शायद InfiniDB की कोशिश करें? स्तंभ डेटा, एक्सेस पैटर्न बड़े बैच अपडेट, श्रेणी आधारित रीड और न्यूनतम तालिका रखरखाव की तरह दिखते हैं।
गंदे

जवाबों:


1

संयोग से मैं भी ग्राहक सहायता में से एक में देख रहा हूं, जहां हमने लचीलेपन के लिए कुंजी-मूल्य जोड़ी संरचना तैयार की है और वर्तमान में तालिका 1.5B पंक्तियों से अधिक है और ईटीएल बहुत धीमा है। अच्छी तरह से मेरे मामले में बहुत सी अन्य चीजें हैं लेकिन क्या आपने उस डिजाइन के बारे में सोचा है। आपके पास सभी 200 स्तंभों के वर्तमान मान के साथ एक पंक्ति होगी, यह पंक्ति की-वैल्यू जोड़ी डिज़ाइन में 200 पंक्तियों में परिवर्तित हो जाएगी। आप दिए गए एसेट और दिनांक के आधार पर इस डिज़ाइन के साथ अंतरिक्ष लाभ प्राप्त करेंगे कि वास्तव में सभी 200 f1 से f200 मानों में कितनी पंक्तियाँ हैं? अगर आप कहते हैं कि 30% od कॉलम का NULL मान है, तो यह आपकी जगह की बचत है। क्योंकि कुंजी-मूल्य जोड़ी डिज़ाइन में यदि वैल्यू आईडी NULL है तो पंक्ति को तालिका में होने की आवश्यकता नहीं है। लेकिन मौजूदा कॉलम संरचना डिजाइन में भी NULL जगह लेता है। (मैं 100% निश्चित नहीं हूं लेकिन अगर आपके पास तालिका में 30 कॉलम NULL अधिक हैं तो NULL 4bytes ले लें)। यदि आप इस डिज़ाइन को देखते हैं और मान लेते हैं कि सभी 35M पंक्तियों में सभी 200 स्तंभों में मान हैं, तो आप वर्तमान db 200 * 35M = 700M पंक्तियाँ तालिका में तुरंत बन जाएंगे। लेकिन यह टेबल स्पेस में बहुत अधिक नहीं होगा जो आपके पास एकल तालिका में सभी स्तंभों के साथ था क्योंकि हम अभी कॉलम को पंक्ति में स्थानांतरित कर रहे हैं। वास्तव में इस ट्रांसपोज़ेशन ऑपरेशन में हमारे पास पंक्तियाँ नहीं होंगी जहाँ मान NULL होते हैं। तो आप वास्तव में इस तालिका के खिलाफ क्वेरी चला सकते हैं और देख सकते हैं कि वास्तव में इसे लागू करने से पहले आप कितने नल हैं और अनुमान लगाते हैं कि आप तालिका आकार को लक्षित करते हैं। लेकिन यह टेबल स्पेस में बहुत अधिक नहीं होगा जो आपके पास एकल तालिका में सभी स्तंभों के साथ था क्योंकि हम अभी कॉलम को पंक्ति में स्थानांतरित कर रहे हैं। वास्तव में इस ट्रांसपोज़ेशन ऑपरेशन में हमारे पास पंक्तियाँ नहीं होंगी जहाँ मान NULL होते हैं। तो आप वास्तव में इस तालिका के खिलाफ क्वेरी चला सकते हैं और देख सकते हैं कि वास्तव में इसे लागू करने से पहले आप कितने नल हैं और अनुमान लगाते हैं कि आप तालिका आकार को लक्षित करते हैं। लेकिन यह टेबल स्पेस में बहुत अधिक नहीं होगा जो आपके पास एकल तालिका में सभी स्तंभों के साथ था क्योंकि हम अभी कॉलम को पंक्ति में स्थानांतरित कर रहे हैं। वास्तव में इस ट्रांसपोज़ेशन ऑपरेशन में हमारे पास पंक्तियाँ नहीं होंगी जहाँ मान NULL होते हैं। तो आप वास्तव में इस तालिका के खिलाफ क्वेरी चला सकते हैं और देख सकते हैं कि वास्तव में इसे लागू करने से पहले आप कितने नल हैं और अनुमान लगाते हैं कि आप तालिका आकार को लक्षित करते हैं।

दूसरा फायदा है प्रदर्शन का। जैसा कि आपने उल्लेख किया है कि डेटा को क्वेरी करने का नया तरीका किसी भी संयोजन में इस f1 से f200 कॉलम में जहां क्लॉज है। कुंजी मूल्य जोड़ी डिजाइन के साथ F1 से F200 एक कॉलम में मौजूद हैं, जो "FildName" कहते हैं और उनके मान दूसरे कॉलम में मौजूद हैं, जो "FieldValue" कहते हैं। आपके पास दोनों स्तंभों पर स्पष्ट सूचकांक हो सकता है। आपकी क्वेरी उन चयनों का UNION होगी।

जहां (FiledName = 'f1' और FieldValue BETWEEN 5 AND 6)

यूनिअन

(फाइलनाम = 'f2' और फील्डवैल्यू बेटन 8 और 10)

आदि.....

मैं तुम्हें कुछ प्रदर्शन संख्या वास्तविक वास्तविक सर्वर के रूप में दूंगा। हमारे पास प्रत्येक सुरक्षा टिकर के लिए 75 मूल्य के कॉलम हैं।


1

इस तरह के डेटा से निपटने में, जहाँ आपको बहुत सी पंक्तियाँ सम्मिलित करने की आवश्यकता होती है और आपको वास्तव में अच्छे विश्लेषणात्मक क्वेरी प्रदर्शन की आवश्यकता होती है (मैं यह धारणा बना रहा हूँ कि यह मामला यहाँ है), आपको लग सकता है कि स्तंभ स्तंभ RDBMS एक अच्छा फिट है । Infobright CE और InfiniDB CE (दोनों स्तंभ भंडारण इंजन MySQL में प्लग किए गए), और Vertica CE के साथ-साथ (MySQL की तरह अधिक PostgreSQL की तरह) पर एक नज़र डालें ... इन सभी सामुदायिक संस्करण मुफ़्त हैं (हालांकि वर्टिका नहीं है खुला स्रोत, यह 3 नोड्स और 1 टीबी डेटा मुफ्त में स्केल करता है)। स्तंभकार आरडीबीएमएस आमतौर पर "बड़ी क्वेरी" प्रतिक्रिया समय प्रदान करते हैं जो पंक्ति-आधारित की तुलना में 10-100X बेहतर होते हैं, और लोड समय जो कि 5-50X बेहतर होते हैं। आपको उन्हें सही तरीके से उपयोग करना होगा या वे बदबू (एकल-पंक्ति संचालन न करें ... सभी कार्यों को एक थोक दृष्टिकोण में करें), लेकिन सही ढंग से उपयोग किया गया वास्तव में रॉक। ;-)

एचटीएच, डेव सिस्क


1
हमारे पास 3 नोड वर्टिका इंस्टॉलेशन में क्लिकस्ट्रीम-टाइप डेटा (स्टॉक टिकर डेटा से अलग नहीं) की लगभग एक बिलियन पंक्तियाँ हैं ... हम लगभग 15 सेकंड में डेटा के पूरे एक दिन का लोड कर सकते हैं, और हमें क्वेरी रिस्पांस टाइम मिलता है। 500 मिलीसेकंड रेंज। आपके मामले में, यह निश्चित रूप से लगता है कि यह देखने लायक होगा।
डेव सिस्क

मैं उसी के लिए वाउच कर सकता हूं। मेरी आखिरी कंपनी में हमारे पास एक 8 नोड वर्टिका क्लस्टर था, जिसके चारों ओर समान पंक्तियों और सरल-ईश समुच्चय वाले प्रश्नों के सेट पूरे 1-3 सेकंड (औसतन) पर लौटे थे। यह हमारे पहले ग्रीनप्लम क्लस्टर की भी 1/4 लागत थी।
bma
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.