2016-02-26 11 views
5

समस्या

हम PostgreSQL के शीर्ष पर जावा में एक वेब अनुप्रयोग का निर्माण कर रहे में आईडी से बाहर चलाने के लिए जा रहा। यह काफी बड़ा और सफल है, और यह कम से कम कुछ और वर्षों तक चलाने में सक्षम होना चाहिए।PostgreSQL: पूर्णांक कॉलम

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

Java's max int is 2^31-1, तो लगभग 2 अरब। यह PostgreSQL's integer type के लिए जाता है। प्रणाली वर्तमान में ~ 10k आईडी प्रतिदिन खा रही है, और दर बढ़ रही है क्योंकि हम नए उपयोगकर्ताओं को प्राप्त करते हैं।

एक दिन, आईडी समाप्त हो जाएगी और ओवरफ़्लो होगा।

प्रश्न

हम स्थिति को ठीक करने के तरीकों की तलाश में हैं। आइए तुरंत स्पष्ट तरीके से बाहर निकलें: जावा के long पर स्विचिंग और पोस्टग्रेस 'bigint एक साफ समाधान है, लेकिन यह टन काम का है। हमें इसे यथासंभव स्थगित करने की आवश्यकता है।

कुछ विचार हम अब तक मिला है:

  • , सब कुछ के लिए एक अनुक्रम का प्रयोग न करें प्रत्येक तालिका का अपना अनुक्रम दे।
    • पेशेवर: यह हमें एन गुना अधिक समय देता है, जहां एन टेबल की संख्या है।
    • विपक्ष: हमें इस तथ्य को पसंद है कि प्रत्येक पंक्ति में एक अद्वितीय आईडी है।
  • कुछ तालिकाओं के लिए अनुक्रम आईडी का उपयोग करना बंद करें। उदाहरण के लिए, ग्राहक घटनाओं वाली एक तालिका को वास्तव में एक आईडी की आवश्यकता नहीं होती है: customer, timestamp एक पूरी तरह से मान्य प्राथमिक कुंजी है।
    • पेशेवर: हमारे कुछ सबसे बड़े आईडी-हॉग इस तरह से बदला जा सकता है।
    • विपक्ष: काम की अनौपचारिक राशि।
  • खाली रिकॉर्ड्स पर आईडी बर्बाद करना बंद करें। यह कुछ उप-तालिकाओं के साथ होता है, जैसे ग्राहक संपर्क जानकारी। रिकॉर्ड हमेशा मौजूद होने से कोड को सरल बना दिया जाता है, लेकिन इसका मतलब है कि कई ग्राहकों के पास एक खाली संपर्क जानकारी रिकॉर्ड संग्रहीत होता है।
    • पेशेवर: हमारे कुछ सबसे बड़े आईडी-हॉग इस तरह से तय किए जा सकते हैं।
    • विपक्ष: हम कोड सादगी खो देते हैं।
  • प्रत्येक नई तालिका को long/bigint का उपयोग एक नए अनुक्रम के साथ करना चाहिए।
    • पेशेवर: कम से कम हम इसे और खराब नहीं करते हैं।
    • विपक्ष: शेष कोड के साथ संपर्क सतह बदसूरत होगी।

इन बाधाओं के तहत, क्या अन्य तरीकों आईडी कमी विलंब होगा?

+2

हाँ इस दर्द है। केवल दो दृष्टिकोण, 1) बिगिन के साथ जाएं और रिफैक्टर (या) 2) सब कुछ के लिए अनुक्रम का उपयोग न करें। मैं refactoring की ओर अधिक दुबला (अन्य दृष्टिकोण, किसी बिंदु पर आप संख्या समाप्त हो जाएगा)। केवल विकल्प दो का चयन करेंगे, जहां हम जानते हैं कि यह एप्लिकेशन संख्या निकास से पहले बंद हो जाएगा। – kosa

+13

"यह काम का एक टन है। हमें इसे यथासंभव स्थगित करने की आवश्यकता है।" यदि आप इसे स्थगित करते हैं तो यह दो टन होगा। गोली मारो और अब करो। –

+0

मुझे यह कहने से नफरत है, लेकिन जैसा कि आप राय और विकल्पों के लिए पूछ रहे हैं, आप शायद बंद होने जा रहे हैं। मैं ऐसा करने वाला नहीं हूं, लेकिन कोई होगा। –

उत्तर

2

लंबे समय तक स्विचिंग एक साफ समाधान से बहुत दूर है। यदि आप बहुत बड़े होते हैं तो केवल एक समझदार विकल्प होता है: यूयूआईडी (yes, PostgreSQL comes with uuid data type)।

128 बिट्स पर इसका आकार 4 पूर्णांक है, लेकिन आप कुछ वर्षों में पूरे एप्लिकेशन से नहीं जाना चाहते हैं और यह सब फिर से करते हैं, है ना? जब आप बहुत बड़े होते हैं तो आपको यूयूआईडी काम करेंगे और आपको अपना डेटा शेड करना होगा। तब आप साझा अनुक्रम प्राप्त नहीं कर पाएंगे, यही कारण है कि यूयूआईडी समझ में आता है।

बोनस के रूप में आप अपनी अद्वितीय संपत्ति को प्रत्येक पंक्ति पर भी रख सकते हैं। है, तो आपको पहले एक स्तंभ जोड़ने और फिर बैचों है, जहां आप एक समय में कुछ हजार रिकॉर्ड अपडेट में ऑनलाइन पलायन कर सकते हैं, PostgreSQL में शून्य वाले कॉलम शामिल सस्ती है:


प्रवासन कि कठिन नहीं है तो आपके पास डाउनटाइम नहीं है।

फिर आप दोनों ही कुंजी के साथ एक ही कोड का परीक्षण कर सकते हैं। क्या जावा में laboratory या scientist जैसा कुछ भी है?

क्या यह काम का एक टन होगा? हां, लेकिन यह स्पष्ट रूप से एक अच्छा संकेत है, अगर आपके पास ऐसा एप्लिकेशन है जो इतना लोकप्रिय है।

मुझे आशा है कि आपने सभी तालिकाओं के लिए समान अनुक्रम का उपयोग करने के साथ एक सबक सीखा है। ईमानदारी से - मुझे वास्तव में उसमें अतिरिक्त मूल्य दिखाई नहीं देता है। यदि आप जानना चाहते हैं कि कोई ऑब्जेक्ट फिट बैठता है, तो आप प्राथमिक कुंजी को अलग-अलग नाम भी दे सकते हैं (उदाहरण के लिए रूम_आईडी, आरक्षण_आईडी, आदि)।

0

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

  1. सभी डीबी प्रकार integer या integer[] के स्तंभों का पता लगाएं। परिणामों को मैन्युअल रूप से जांचें और प्रकार के कॉलम हटाएं, उदाहरण के लिए, text[]

    SELECT * 
    FROM information_schema.columns cls 
    JOIN information_schema.tables tbl ON cls.table_name = tbl.table_name 
    WHERE 
        cls.table_schema = '<my schema>' 
        AND cls.data_type = 'integer' OR cls.data_type = 'ARRAY' 
        AND tbl.table_type = 'BASE TABLE'; 
    
  2. उन स्तंभों में से प्रत्येक के लिए एक डेटा प्रकार परिवर्तन DDL तैयार:

    ALTER TABLE <one of the tables found> 
    ALTER COLUMN <one of its integral columns> 
    TYPE bigint; 
    
  3. इस खूबसूरती से काम करता है, VIEW रों को छोड़कर: वे मेरे उनकी वापसी प्रकार बदल रहा पसंद नहीं है। मुझे उन सभी को फिर से बनाने की जरूरत है - अनुक्रम

    1. सभी विचारों को छोड़ दें।
    2. कॉलम प्रकार बदलें।
    3. सभी विचारों को दोबारा बनाएं।
  4. ,, एप्लिकेशन को बंद करें चरण 3 से उन्नयन स्क्रिप्ट चलाने के सभी टेबल पर VACUUM और ANALYZE चलाकर धीमी गति से प्रश्नों को ठीक।
  5. परीक्षण कोड चलाएं और स्रोत कोड में समस्याएं ठीक करें - उदाहरण के लिए, bigint[] को integer[] पर नहीं डाला जा सकता है।

How to export/backup VIEWs only?