Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

तेजी से बढ़ती Users टेबल में महारत: स्वच्छ, स्केलेबल डिज़ाइन के लिए रणनीतियाँ

क्लाइंट वहां कैसे पहुंचा?

विवरण में गोता लगाने से पहले, आइए यह समझने की कोशिश करें कि एक ऐप इस स्थिति में कैसे पहुंच सकता है। हम एक साधारण users टेबल से शुरू करते हैं। कुछ हफ्तों के बाद, हमें अंतिम साइन-इन समय निर्धारित करने में सक्षम होने की आवश्यकता होती है इसलिए हम users.last_sign_in_at जोड़ते हैं। फिर हमें उपयोगकर्ता का नाम जानने की आवश्यकता होती है। हम first_name और last_name जोड़ते हैं। ट्विटर हैंडल? एक और कॉलम। GitHub प्रोफाइल? फोन नंबर? कुछ महीनों के बाद टेबल दिमाग को चकरा देने वाली बन जाती है।

इसमें क्या गलत है?

इतनी बड़ी टेबल कई समस्याओं का संकेत देती है:

  1. User की कई असंबंधित जिम्मेदारियां हैं। इससे इसे समझना, बदलना और परीक्षण करना अधिक कठिन हो जाता है।
  2. ऐप और डेटाबेस के बीच डेटा का आदान-प्रदान अतिरिक्त बैंडविड्थ की आवश्यकता होती है।
  3. ऐप को भारी मॉडल को स्टोर करने के लिए अधिक मेमोरी की आवश्यकता होती है।

ऐप हर अनुरोध पर प्रमाणीकरण और प्राधिकरण उद्देश्यों के लिए User लाता था लेकिन आमतौर पर केवल कुछ कॉलम का उपयोग करता था। समस्या को ठीक करने से डिज़ाइन और प्रदर्शन दोनों में सुधार होगा।

एक टेबल निकालना

हम इस समस्या को कम उपयोग किए जाने वाले कॉलम को एक नई टेबल (या टेबल्स) में निकालकर हल कर सकते हैं। उदाहरण के लिए, हम प्रोफ़ाइल जानकारी (first_name, आदि) को profiles में निम्न चरणों के साथ निकाल सकते हैं:

  1. प्रोफ़ाइल-संबंधित कॉलम को users में डुप्लिकेट करने वाले कॉलम के साथ profiles बनाएं।
  2. users में profile_id जोड़ें। इसे अभी NULL पर सेट करें।
  3. users में प्रत्येक पंक्ति के लिए, profiles में एक पंक्ति डालें जो प्रोफ़ाइल-संबंधित कॉलम को डुप्लिकेट करती है।
  4. users में संबंधित पंक्ति के profile_id को चरण 3 में डाली गई पंक्ति पर इंगित करें।
  5. नहीं users.profile_id को नॉन-NULL बनाएं। ऐप अभी तक इसके अस्तित्व से अवगत नहीं है इसलिए यह टूट जाएगा।

हमें users.first_name के संदर्भ को profiles.first_name से बदलने की आवश्यकता है और इसी तरह। यदि हम केवल कुछ कॉलम निकाल रहे हैं जिनके कुछ संदर्भ हैं तो मैं मैन्युअल रूप से ऐसा करने की सलाह देता हूं। लेकिन जैसे ही हम खुद को सोचते हुए पकड़ते हैं "ओह, नहीं। यह अब तक का सबसे खराब काम है!" हमें एक विकल्प की तलाश करनी चाहिए।

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

पढ़ें, यदि आप उत्सुक हैं कि मेरे क्लाइंट ने समस्या को कैसे हल किया।

एक बार में एक लाइन कोड ठीक करना

सबसे वृद्धिशील दृष्टिकोण एक समय में पुराने कॉलम के एक संदर्भ को ठीक करना है। आइए first_name को users से profiles में ले जाने पर ध्यान केंद्रित करें।

सबसे पहले, इसके साथ Profile बनाएं:

rails generate model Profile first_name:string

फिर users से profiles में एक संदर्भ जोड़ें और users.first_name को profiles में कॉपी करें:

class ExtractUsersFirstNameToProfiles < ActiveRecord::Migration
  # प्रोडक्शन कोड पर निर्भरता तोड़ने के लिए मॉडल को पुनः परिभाषित करें। हमें
  # कॉलबैक आदि के बिना वेनिला मॉडल चाहिए। साथ ही, भविष्य में एक मॉडल को हटाने से
  # माइग्रेशन टूट सकता है।
  class User < ActiveRecord::Base; end
  class Profile < ActiveRecord::Base; end
  
  def up
    add_reference :users, :profile, index: true, unique: true, foreign_key: true
    User.find_each do |user|
      profile = Profile.create!(first_name: user.first_name)
      user.update!(profile_id: profile.id)
    end
    change_column_null :users, :profile_id, false
  end
  
  def down
    remove_reference :users, :profile
  end
end

क्योंकि यह प्रत्येक उपयोगकर्ता को ठीक एक प्रोफ़ाइल रखने के लिए मजबूर करता है, users से profiles में एक संदर्भ विपरीत संदर्भ के लिए बेहतर है।

डेटाबेस संरचना के साथ, हम User से Profile को first_name सौंप सकते हैं। मेरे क्लाइंट की कई आवश्यकताएं थीं:

  1. एक्सेसर्स को संबद्ध Profile का उपयोग करना चाहिए। उन्हें यह भी लॉग करना चाहिए कि डिप्रिकेटेड एक्सेसर को कहां से कॉल किया गया था।
  2. User को सेव करने से स्वचालित रूप से Profile सेव होना चाहिए ताकि डिप्रिकेटेड एक्सेसर्स का उपयोग करने वाले कोड को तोड़ने से बचा जा सके।
  3. User#first_name_changed? और अन्य ActiveModel::Dirty विधियों को अभी भी काम करना चाहिए।

इसका मतलब है User को इस तरह दिखना चाहिए:

class User < ActiveRecord::Base
  # हमें autosave की आवश्यकता है क्योंकि क्लाइंट कोड Profile#first_name से अनजान हो सकता है
  # और अभी भी User#first_name का संदर्भ दे सकता है।
  belongs_to :profile, autosave: true
  
  def first_name
    log_backtrace(:first_name)
    profile.first_name
  end
  
  def first_name=(new_first_name)
    log_backtrace(:first_name)
    # super कॉल करें ताकि User#first_name_changed? और इसी तरह अपेक्षा के अनुरूप काम करते रहें।
    super
    profile.first_name = new_first_name
  end
  
  private
  
  def log_backtrace(name)
    filtered_backtrace = caller.select do |item|
      item.start_with?(Rails.root.to_s)
    end
    Rails.logger.warn(<<-END)
      A reference to an obsolete attribute #{name} at:
      #{filtered_backtrace.join("\n")}
    END
  end
end

इन परिवर्तनों के बाद, ऐप वही काम करता है लेकिन थोड़ा धीमा हो सकता है क्योंकि Profile के अतिरिक्त संदर्भों के कारण (यदि प्रदर्शन एक मुद्दा बन जाता है तो AppSignal जैसे टूल का उपयोग करें)। कोड लिगेसी विशेषताओं के सभी संदर्भों को लॉग करता है, यहां तक कि अन-ग्रेपेबल वाले (जैसे user[attr] = ... या user.send("#{attr}=", ...)) ताकि हम उन सभी का पता लगा सकें जब grep अनुपयोगी हो।

इस बुनियादी ढांचे के साथ, हम users.first_name के एक डिप्रिकेटेड संदर्भ को नियमित शेड्यूल पर ठीक करने के लिए प्रतिबद्ध हो सकते हैं, उदाहरण के लिए हर सुबह (दिन की शुरुआत एक त्वरित जीत के साथ करने के लिए) या दोपहर के आसपास (एक केंद्रित सुबह के बाद किसी आसान चीज़ पर काम करने के लिए)। यह प्रतिबद्धता आवश्यक है क्योंकि हमारा लक्ष्य इस मुद्दे को ठीक करने के लिए मानसिक बाधाओं को कम करना है। उपरोक्त कोड को बिना कार्रवाई किए छोड़ देने से ऐप और भी अधिक खराब होगा।

सभी डिप्रिकेटेड संदर्भों को हटाने के बाद (और grep और लॉग्स के साथ पुष्टि करने के बाद) हम अंततः users.first_name को हटा सकते हैं:

class RemoveUsersFirstName < ActiveRecord::Migration
  def change
    remove_column :users, :first_name, :string
  end
end

हमें User में जोड़े गए कोड से भी छुटकारा पाना चाहिए क्योंकि यह अब आवश्यक नहीं है।

सीमाएं

यह विधि आपके मामले पर लागू हो सकती है लेकिन इसकी कुछ सीमाओं को ध्यान में रखें:

  • यह User.update_all जैसे बल्क क्वेरी को नहीं संभालता।
  • यह कच्चे SQL क्वेरी को नहीं संभालता।
  • यह मंकी-पैच को तोड़ सकता है (याद रखें कि निर्भरताएं उन्हें भी पेश कर सकती हैं)।
  • User और Profile आउट ऑफ सिंक हो सकते हैं, यदि profiles.first_name अपडेट किया गया है लेकिन users.first_name नहीं।

आप उनमें से कुछ को दूर करने में सक्षम हो सकते हैं। उदाहरण के लिए, आप एक सर्विस ऑब्जेक्ट या Profile पर कॉलबैक के साथ मॉडल को सिंक में रख सकते हैं। या यदि आप PostgreSQL का उपयोग करते हैं तो आप अंतरिम में एक मैटेरियलाइज़्ड व्यू का उपयोग करने पर विचार कर सकते हैं।

बस इतना ही!

लेख का सबसे महत्वपूर्ण सबक गंध वाले कोड से बचें नहीं बल्कि इसे सीधे निपटें। यदि कार्य भारी है तो नियमित शेड्यूल पर पुनरावृत्तियों से काम करें। लेख ने एक टेबल निकालते समय विचार करने के लिए एक विधि प्रस्तुत की। यदि आप इसे लागू नहीं कर सकते तो कुछ और खोजें। यदि आपको कोई अंदाजा नहीं है कि कैसे तो बस मुझे एक लाइन ड्रॉप करें। मैं मदद करने की कोशिश करूंगा। अपने बिट्स को सड़ने न दें।

  1. विंडोज पीसी पर MX प्लेयर इंस्टॉल करें: चरण-दर-चरण गाइड विंडोज पीसी पर MX प्लेयर इंस्टॉल करें: चरण-दर-चरण गाइड

    इससे कोई फर्क नहीं पड़ता कि आप एक मूवी जंकी हैं या एक नियमित एंड्रॉइड उपयोगकर्ता, आपने MX प्लेयर के बारे में सुना होगा। उन लोगों के लिए जो MX प्लेयर के बारे में नहीं जानते, यह एक मीडिया प्लेयर है जो आपको सभी प्रकार के ऑडियो और वीडियो मुफ्त में चलाने देता है। MX प्लेयर आपको जिन प्रकार के वीडियो चलाने

  1. विंडोज 10 प्रदर्शन बढ़ाएं: अपने PC को तेज करने के विशेषज्ञ चरण विंडोज 10 प्रदर्शन बढ़ाएं: अपने PC को तेज करने के विशेषज्ञ चरण

    यदि आप अपने विंडोज 10 कंप्यूटर को तेज करने के तरीके खोज रहे हैं, तो आप सही जगह पर हैं। आज तक मैंने कई विंडोज 10 कंप्यूटर देखे और ठीक किए हैं जो धीमे चल रहे थे, यहां तक कि नए - और कथित रूप से तेज - PC भी। मेरे अनुभव के अनुसार, विंडोज कई कारणों से धीमा चल सकता है जो सिस्टम के प्रदर्शन को प्रभावित करते

  1. फेसबुक का विश्वास पुनर्प्राप्ति: प्लेटफॉर्म कैसे आत्मविश्वास पुनर्निर्माण कर रहा है फेसबुक का विश्वास पुनर्प्राप्ति: प्लेटफॉर्म कैसे आत्मविश्वास पुनर्निर्माण कर रहा है

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