যখন আপনি একটি যুবক প্রজেক্টে কাজ করছেন, তবে আপনি liên tục সিদ্ধান্ত নিচ্ছেন যা পরবর্তীতে স্কেল করা সহজ বা কঠিন করবে। কখনো কখনো শর্ট-টার্ম গেইন বেছে নেওয়া ভালো, কিছু টেকনিক্যাল ডেট নেওয়া যাতে আপনি দ্রুত শিপ করতে পারেন। কিন্তু অন্য সময় আমরা টেকনিক্যাল ডেট নিই কারণ আমরা জানতাম না বিকল্পটি আছে।
আমি এটি বলতে পারি কারণ Honeybadger-এ, আমরা কিছুটা কিছু করেছি যা জীবন আমাদের জন্য অনেক কঠিন করে দিয়েছিল। হ্যাঁ যদি আমরা কিছু কী পয়েন্ট বুঝতাম, তবে স্কেলিং অনেক কম পেইনফুল হত।
UUID ব্যবহার করুন
আপনি যখন "প্রাইমারি কি" বলেন, আমাদের অধিকাংশ লোক ভাবি একটি অটো-ইনক্রিমেন্টিং নাম্বার। এটি ছোট সিস্টেমের জন্য ভালো কাজ করে, কিন্তু স্কেল করার সাথে সাথে একটি বড় সমস্যা তৈরি করে।
যেকোনো মুহূর্তে শুধু একটি ডাটাবেস সার্ভার প্রাইমারি কি জেনারেট করতে পারে। এর মানে সকল রাইটস একটি একক সার্ভারের মধ্য দিয়ে যেতে হবে। আপনি যদি প্রতি সেকেন্ডে হাজার হাজার রাইট করতে চান তবে এটা খারাপ খবর।
প্রাইমারি কি হিসেবে UUID ব্যবহার করা এই সমস্যাকে বাইপাস করে। আপনি যদি সেগুলোর সাথে পরিচিত না হন, UUID হলো ইউনিক আইডেন্টিফায়ার যা এইরকম দেখায়: 123e4567-e89b-12d3-a456-426655440000।
উইকিপিডিয়া এগুলোর বর্ণনা এভাবে করে:
স্ট্যান্ডার্ড মেথড অনুযায়ী জেনারেট করা হলে, UUID গুলো প্র্যাক্টিক্যালি ইউনিক, কোনো সেন্ট্রাল রেজিস্ট্রেশন অথোরিটি বা জেনারেটর পক্ষের মধ্যে কোনো কোঅর্ডিনেশন ছাড়া। UUID ডুপ্লিকেট হওয়ার সম্ভাবনা শূন্য নয়, কিন্তু এতটাই শূন্যের কাছাকাছি যে নগণ্য।
অতএব, কেউ UUID তৈরি করতে পারে এবং কোনো কিছুর আইডেন্টিফাই করতে ব্যবহার করতে পারে প্রায় নিশ্চিততার সাথে যে আইডেন্টিফায়ারটি ইতিমধ্যে তৈরি করা অন্য কোনো কিছু আইডেন্টিফাই করার জন্য ডুপ্লিকেট নয়, এবং ভবিষ্যতে ডুপ্লিকেট হবে না। স্বাধীন পক্ষের দ্বারা UUID দিয়ে লেবেল করা ইনফরমেশন পরবর্তীতে একটি ডাটাবেসে কম্বাইন করা যাবে, অথবা একই চ্যানেলের মাধ্যমে ট্রান্সমিট করা যাবে, আইডেন্টিফায়ারের মধ্যে দ্বন্দ্ব রেজলভ করতে ছাড়া।
যখন আপনি UUID প্রাইমারি কি হিসেবে ব্যবহার করেন, তবে সকল রাইটস আর একটি একক ডাটাবেসের মধ্য দিয়ে যেতে হয় না। বদলে আপনি সেগুলো অনেক সার্ভারের বাইরে ছড়িয়ে দিতে পারেন।
ব্যতীত, এগুলো আপনাকে ফ্লেক্সিবিলিটি দেয় যেন আপনি একটি রেকর্ডের আইডি ডাটাবেসে সেভ হওয়ার আগে জেনারেট করতে পারেন। এটি উপযোগী হতে পারে আপনি যদি রেকর্ডটি একটি ক্যাশ বা সার্চ সার্ভারে পাঠাতে চান, কিন্তু ডাটাবেস ট্রানজ্যাকশন কমপ্লিট হওয়ার জন্য অপেক্ষা করতে চান না।
রেলস অ্যাপে ডিফল্টরূপে UUID ইম্প্লিমেন্ট করা সহজ। শুধু কনফিগ ফাইল এডিট করুন:
# config/application.rb
config.active_record.primary_key = :uuid
আপনি একটি নির্দিষ্ট টেবিলের জন্য রেলস মাইগ্রেশনে UUID ব্যবহার করতে পারেন:
create_table :users, id: :uuid do |t|
t.string :name
end
এটি একটি সিম্পল কনফিগারেশন অপশন যা, আপনি যদি ডেভেলপমেন্ট শুরু করার সময়ই ইম্প্লিমেন্ট করেন, তবে স্কেল করার চেষ্টা করার সময় আপনাকে বিশাল কষ্ট থেকে বাঁচাবে। এক্সট্রা বোনাস হিসেবে, এটি বট এবং খারাপ অ্যাক্টরদের জন্য আপনার প্রাইভেট URL গেস করা কঠিন করে তোলে।
কাউন্টস এবং কাউন্টারস
একবার খোঁজা শুরু করলে, কাউন্ট এবং কাউন্টার সব জায়গায় আছে। আপনার ইমেইল ক্লায়েন্ট আনরিড ইমেইলের সংখ্যা দেখায়। ব্লগগুলোর পেজিনেশন ফুটার থাকে যা টোটাল পোস্টের সংখ্যা ব্যবহার করে পেজের সংখ্যা ক্যালকুলেট করে।
কাউন্টারের সাথে দুটি স্কেলিং সমস্যা আছে:
select count(*) from usersএর মত ডাটাবেস কোয়েরি ذاتভাবেই স্লো। সেগুলো লিটারালি রেকর্ডসেটের প্রতিটি রেকর্ড দিয়ে লুপ করে রেজাল্ট জেনারেট করতে। আপনার কাছে এক মিলিয়ন রেকর্ড থাকলে, এটা কিছুক্ষণ লাগবে।- "কাউন্টার ক্যাশ" ব্যবহার করে কাউন্টার দ্রুত করার চেষ্টা কাজ করে, কিন্তু এটা আপনার রাইটস অনেক ডাটাবেস সার্ভারের মধ্যে ছড়িয়ে দেওয়ার ক্ষমতা সীমাবদ্ধ করে।
সबচেয়ে সহজ সমাধান হলো যেখানে সম্ভব কাউন্টার এড়িয়ে চলা। এটি প্রারম্ভিক ডিজাইন করার সময় অনেক সহজ।
উদাহরণস্বরূপ, আপনি কাউন্টের বদলে ডেট-রেঞ্জ দিয়ে পেজ করতে বেছে নিতে পারেন। আপনি এমন একটি মাইল্ডলি-উপযোগী σταтистиক দেখানো বাদ দিতে পারেন যা পরবর্তীতে জেনারেট করা নরক সমান হবে। আপনি বুঝলেন।
এক্সপায়ারিং এবং ওয়েয়ারহাউসিং ডেটা
আপনার কাছে কতটুকু RAM, CPU এবং ডিস্ক IO আছে সেটার ওপর নির্ভর করে একটি সিঙ্গেল পোস্টগ্রেস টেবিলে আপনি কতটুকু ডেটা স্টোর করতে পারবেন সেটার একটি উপরের সীমা আছে। এর মানে একটি সময় আসবে যখন আপনাকে পুরানো ডেটা আপনার মেইন টেবিল থেকে সরাতে হবে।
একটি সিম্পল কেস দেখি। আপনি এক বছরের পুরনো রেকর্ড ডিলিট করতে চান একটি ডাটাবেসে যা কয়েক গিগাবাইট বড়।
আপনি যদি এই ইস্যুতে আগে কখনো ডাল না থাকেন, তবে আপনি আকৃষ্ট হতে পারেন এমন কিছু করার জন্য:
MyRecords.where("created_at < ?", 1.year.ago).destroy
সমস্যাটি হলো এই কোয়েরি দিন বা সপ্তাহ ধরে চলে। আপনার ডাটাবেস শুধু খুব বড়।
এটি একটি বিশেষভাবে পেইনফুল সমস্যা, কারণ প্রায়শই আপনি বুঝতে পারেন না আপনার কাছে এটি আছে যতক্ষণ না অনেক লেট হয়ে যায়। কোথাও কেউ ডেটা পার্জিং স্ট্র্যাটেজি নিয়ে চিন্তা করে না যখন তাদের কোম্পানি যুবক এবং তাদের ডাটাবেসে ১,০০০ রেকর্ড থাকে।
যদি আপনি আগে থেকে প্ল্যান করেন, তবে একটি সহজ সমাধান আছে। শুধু আপনার টেবিল পার্টিশন করুন। আপনার সকল ডেটা my_records-এ লেখার বদলে, আপনি এই সপ্তাহের ডেটা my_records_1-এ লিখুন এবং আগামী সপ্তাহের ডেটা my_records_2-এ। যখন গত সপ্তাহের ডিলিট করার Reihe, শুধু drop table my_records_1 করুন। ডিলিটের বিপরীতে, এই কোয়েরি খুব দ্রুত কমপ্লিট হয়।
ডেট ছাড়া অন্য ফিল্ড দিয়েও পার্টিশন করা সম্ভব। আপনার ইউজ-কেসের জন্য যা সেন্সIBLE।
এখানে pg_partman নামে একটি পোস্টগ্রেস এক্সটেনশন আছে যা সকল ডিটেইল হ্যান্ডেল করে এবং আপনাকে আপনার কোডের এক লাইনও পরিবর্তন ছাড়া ডাটাবেস পার্টিশন করতে দেয়। অথবা, আপনি যদি রুবিতে পার্টিশনিং ম্যানেজ করতে চান, তবে partitionable নামে একটি হ্যান্ডি জেম আছে।
বিচ্ছেদের কথা
আপনি যখন পরবর্তীবার কোনো প্রজেক্ট স্ক্র্যাচ থেকে বানাবেন, আমি আপনাকে উৎসাহিত করব কিছু মুহূর্ত স্কেলিং নিয়ে চিন্তা করতে। এর ওপর অবসেস করবেন না। HAML নাকি ERB ব্যবহার করবেন সেটা নিয়ে দিন দিন চিন্তা করবেন না। কিন্তু নিজেকে জিজ্ঞেস করুন কি কোনো ইزی উইন নেই যা আপনি আগে থেকে প্ল্যান করে সহজে পেতে পারেন।