ডাটাবেস: ইনডেক্সিং নিয়ে কিছু কথা

ডাটাবেস: ইনডেক্সিং নিয়ে কিছু কথা
২৭ মার্চ ২০১৮, মঙ্গলবার

আমার এই ব্লগের একটা মূল উদ্দেশ্য হচ্ছে কাজ করতে গিয়ে শেখা নতুন কোনো টুল, টেকনিক বা আইডিয়া সবার সাথে শেয়ার করা।  আরেকটা উদেশ্য হচ্ছে নিজের জন্য নোট করে রাখা, যাতে ভবিষ্যতে দরকারের সময় খুঁজে পেতে সুবিধা হয়, কাজে লাগে। লেখা পড়ে এ ব্যাপারে আমাকে এক্সপার্ট ভাবা সম্পূর্ণ ভুল হবে, আমি এখনো শিখছি আর ব্লগের লেখায় ভুল থাকতেই পারে। কেউ ভুল পেলে ধরিয়ে দিলে খুশি হবো।

কয়েকদিন আগে ডাটাবেসে ইনডেক্সিং করতে হলো প্রথমবারের মতো।  ইনডেক্সিং কী জিনিস সেটা আমার মোটামুটি আগেই জানা ছিল।  যেটা জানা ছিল না, বা ঐভাবে ভেবে দেখি নাই, তা হলো, ডাটাবেসে ইনডেক্সিং করা হয় কোনো একটা টেবিলের কলামে। পুরো টেবিলের উপর না!


একটা উদাহরণ দিয়ে ব্যাপারটা বোঝা যাক, ধরা যাক, আমাদের একটা Previous_Passwords টেবিল আছে, যেটা ইউসার -এর আগের বা previous পাসওয়ার্ড সেভ করে রাখে :

Previous_Passwords টেবিল 

এই টেবিলের প্রাইমারি কী Previous_Passwords_Id, কিন্তু আরেকটা কলাম আছে User_Id, যেটা কীনা ফরেন কী (অর্থাৎ অন্য কোনো টেবিলে প্রাইমারি কী)।  প্রাইমারী কী নিজে থেকেই sorted অবস্থায় থাকবে, কিন্তু ফরেন কী sorted থাকবে না, ঠিক?

এখন আমাদের যদি অনেক বেশি (অর্থাৎ বেশি সংখ্যক বার)  ইউসার-এর User_Id ব্যবহার করে previous password খুঁজে বের করতে হয়, তাহলে এই read অপারেশন বেশ এক্সপেন্সিভ হবে। কেননা যেহেতু User_Id কলাম sorted  না, প্রতিবারই টার্গেট User_Id খুঁজতে সময় লাগবে। আর তাই, এই User_Id কলাম ইনডেক্সিং করে ফেললে একই কাজ করতে অনেক কম সময় লাগবে, read অপারেশন অনেক ইফিসিয়েন্ট হবে।

এখন প্রশ্ন হচ্ছে, User_Id  কলাম ইনডেক্সিং করবো কিভাবে?

সহজেই, নিচের কম্যান্ড ব্যবহার করে :

CREATE INDEX IX_Previous_Passwords_UserId
    ON Previous_Passwords (User_Id);

এইখানে, "IX_Previous_Passwords_UserId" ইনডেক্সটার নাম।  IX দিয়ে কিন্তু রোমান হরফে ৯ বোঝানো হচ্ছে না, Index -কে সংক্ষেপে IX লেখা হয়েছে।

এতটুকু হলেই ভালো ছিল।  কিন্তু না, ঝামেলার এইখানেই শেষ না।  প্রথমতঃ ইনডেক্সিং করার সময় Page Split বলে একটা ব্যাপার আছে, ঐটা মাথায় রাখতে হবে।  সেটা আবার কী ??

ডিটেইলসে না গিয়ে বলি: যখন ডাটা একটা ইনডেক্স -এর লিফ নোড বা পেজ -এ রাখা হয়, তখন যদি row গুলোর মাঝে কোনো খালি জায়গা না রেখে পর পর রেখে যাওয়া হয়, তখন পেজ ভর্তি হয়ে গেলে নতুন row যোগ করতে গেলে জায়গা পাওয়া যায়না। তখন (প্রায় ৫০%) ডাটা কপি করে পাশের পেজে নিয়ে রাখা হয়।  পাশের পেজে জায়গা না থাকলে একই পদ্ধতিতে তার পাশের পেজে ডাটা কপি করে রাখা হয় - এই ব্যাপারটাকে Page Split বলে।  এই লিংকের ভিডিওতে ব্যাপারটা ছবি দিয়ে বোঝানো আছে, এই আর্টিকেলটাও ভালো - দেখে নিতে পারেন। এটা বেশ expensive একটা প্রসেস।

তাই প্রতি পেজে কিছু জায়গা খালি রাখা ভালো।  পেজ পুরো না ভরে, row গুলোর মাঝে কিছু খালি জায়গা রেখে দিলে Page Split হবার সম্ভাবনা কমে যাবে। কিন্তু বেশি খালি রাখা যাবে না।  তাতে করে আবার জায়গা নষ্ট (waste) হবে, তার থেকেও বড় ব্যাপার, ডাটা ছড়ানো থাকায় ডিস্ক I/O বেড়ে গিয়ে read অপারেশন আবার স্লো হয়ে যাবে।

আমার কাজের জায়গায় এরা ইনডেক্সের পেজ ৯০% ভরে বা ফিল করে রাখে। এটা করতে হয় নিচের কমান্ড (FILLFACTOR) ব্যবহার করে।

CREATE INDEX IX_Previous_Passwords_UserId
    ON Previous_Passwords (User_Id)
 WITH (FILLFACTOR = 90);

এবার আরেকটা ব্যাপার বলি।  এই ইনডেক্স তৈরি করতে গিয়ে যেন টেবিল আবার লক না হয়ে যায়, অন্য query বা অপারেশন যেন চালু থাকে (অর্থাৎ টেবিল যেন ONLINE বা available থাকে), সেটা নিশ্চিত করতে আরেকটা প্যারামিটার সেট করতে হয়, এভাবে:

CREATE INDEX IX_Previous_Passwords_UserId
    ON Previous_Passwords (User_Id)
    WITH (FILLFACTOR = 90, ONLINE = ON);

এই লিংকের আর্টিকেলে ONLINE -এ ইনডেক্স তৈরির ব্যাপারটা ভালোভাবে লেখা আছে।

সব শেষে, আরেকটা জিনিস শিখলাম। ডাটাবেসে যেকোনো ইনডেক্স বা টেবিল তৈরি করতে যে স্ক্রিপ্ট লেখা হয়, সেটার কাউন্টার রোলব্যাক স্ক্রিপ্টও লিখতে হয়, যেটা কিনা তৈরি করা ইনডেক্স বা টেবিল ডিলিট করবে। শুধু স্ক্রিপ্ট আর রোলব্যাক স্ক্রিপ্ট লিখলেই হবে না, এমন ভাবে লিখতে হবে যেন একই স্ক্রিপ্ট বার বার চালানো যায়।  উদাহরণ দিয়ে ব্যাখ্যা করি : উপরের ইনডেক্স তৈরি করার কম্যান্ড একটা স্ক্রিপ্ট- এ লিখে তা প্রথমবার রান করলে বা চালালে ইনডেক্স তৈরি হবে।  কিন্তু আরেকবার চালালেই তা ফেল করবে, কেননা ইনডেক্সটা তো ইতিমধ্যেই তৈরি হয়ে গেছে!! অর্থাৎ, ইনডেক্স অলরেডি তৈরি করা আছে কিনা তা চেক করে তবেই ইনডেক্স তৈরী করতে হবে।

যাক ফাইনালি, স্ক্রিপ্ট আর রোলব্যাক স্ক্রিপ্টের চেহারা যেটা দাঁড়ালো তা নিচের মতো:


ইনডেক্স তৈরির স্ক্রিপ্ট 
ইনডেক্স রোলব্যাক স্ক্রিপ্ট 






ধন্যবাদ।
--ইশতিয়াক।









No comments:

Post a Comment

কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম

কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম  ৩ ফেব্রুয়ারি, শনিবার, ২০২৪ রেগুলার এক্সপ্রেশন (Regular Exp...