পেজিং, ভার্চুয়ালাইজেশন, স্মার্ট ফিল্টারিং ও ভাল কুয়েরি ব্যবহার করে 100k সারি সহ দ্রুত ড্যাশবোর্ড তালিকা কীভাবে বানাবেন—তাই ভিতরের টুলগুলো তৎক্ষণাত ও স্ন্যাপি থাকে।

একটি লিস্ট স্ক্রিন সাধারণত ঠিকঠাক লাগে যতক্ষণ না তা হঠাৎ ধীর হয়ে যায়। ব্যবহারকারীরা ছোট ছোট স্টল লক্ষ্য করতে শুরু করেন: স্ক্রলিংয়ে ঝাঁকুনি, আপডেটের পর পেজ কিছুকাল আটকে থাকা, ফিল্টার সেকেন্ড নেয়, এবং প্রতিটি ক্লিকে স্পিনার দেখা যায়। কখনও কখনও ব্রাউজারের ট্যাব ফ্রিজড মনে হয় কারণ UI থ্রেড ব্যস্ত।
100k সারি একটি প্রচলিত মোড় কারণ এটি সিস্টেমের প্রতিটি অংশকে একসাথে স্ট্রেস করে। ডেটাসেট ডাটাবেসের জন্য এখনও স্বাভাবিক, কিন্তু ব্রাউজার ও নেটওয়ার্কে ছোট অদক্ষতাগুলো স্পষ্ট করে দেয়। সবকিছু একসাথে দেখানোর চেষ্টা করলে সাধারণ একটি স্ক্রিন ভারী পাইপলাইনে পরিণত হয়।
লক্ষ্য সব সারি রেন্ডার করা নয়। লক্ষ্য হলো কারো জন্য দ্রুত দরকারি জিনিসটি খুঁজে দেয়া: সঠিক প্রথম ৫০ সারি, পরের পেজ, অথবা ফিল্টারের ভিত্তিতে একটি সংকীর্ণ অংশ।
কাজকে চার ভাগে ভাগ করা কাজে লাগে:
এই যেকোনো অংশ ব্যয়বহুল হলে পুরো স্ক্রিন ধীর মনে হয়। একটি সিম্পল সার্চ বক্স এমন একটি অনুরোধ ট্রিগার করতে পারে যে 100k সারি সাজায়, হাজার হাজার রেকর্ড রিটার্ন করে, এবং ব্রাউজারকে সেগুলো রেন্ডার করতে বাধ্য করে—এভাবেই টাইপিং ল্যাগি হয়ে যায়।
দলগুলো দ্রুত ভিতরের টুল বানালে (কখনও কখনও Koder.ai-এর মতো ভিব-কোডিং প্ল্যাটফর্ম ব্যবহার করে), লিস্ট স্ক্রিন সাধারণত সেই জায়গা যেখানে প্রকৃত ডেটা বৃদ্ধিই “ডেমো ডেটাসেটে চলে” এবং “প্রতিদিন তৎক্ষণাত লাগে”—এই ফাঁক দেখায়।
অপটিমাইজ করার আগে ঠিক করুন এই স্ক্রিনে দ্রুত হওয়া মানে কী। অনেক দল থ্রুপুট (সবকিছু লোড করা) ধরে চালায়, অথচ ব্যবহারকারীরা বেশিরভাগ ক্ষেত্রেই ল্যাটেন্সি কম থাকাই চায় (দ্রুত কিছু দেখতে পাওয়া)। একটি লিস্ট ততক্ষণই তৎক্ষণাত মনে হয় যতক্ষণ প্রথম ২০–৫০ সারি দ্রুত আসে এবং ইন্টারঅ্যাকশন মসৃণ থাকে—even যদি পুরো 100k সারি কখনো লোড না হয়।
একটি প্র্যাকটিক্যাল লক্ষ্য হলো পুরো লোড নয়, প্রথম সারি দেখা পর্যন্ত সময়। ব্যবহারকারীরা পেইজে বিশ্বাস স্থাপন করে যখন তারা প্রথম কটি সারি দ্রুত দেখে এবং ইন্টারঅ্যাকশন মসৃণ থাকে।
কিছু ছোট সংখ্যা বেছে নিন যেগুলো আপনি প্রতিবার পরিবর্তন করলে ট্র্যাক করতে পারবেন:
COUNT(*) এবং বিস্তৃত SELECT)এগুলো সাধারণ লক্ষণগুলোর সঙ্গে মানচিত্র করে। যদি স্ক্রোল করার সময় ব্রাউজার CPU স্পাইক করে, ফ্রন্টএন্ড প্রতি সারিতে বেশী কাজ করছে। যদি স্পিনার অপেক্ষা করে কিন্তু স্ক্রোল ঠিক থাকে, তাহলে ব্যাকএন্ড বা নেটওয়ার্ক সমস্যা থাকে। যদি রিকোয়েস্ট দ্রুত কিন্তু পেজ এখনও ফ্রিজ করে, প্রায়ই তা রেন্ডারিং বা ক্লায়েন্ট-সাইড ভারী প্রসেসিং।
একটি সরল পরীক্ষা করুন: UI একই রেখে, ব্যাকএন্ডকে সাময়িকভাবে কেবল 20টি সারি রিটার্ন করতে বলুন একই ফিল্টার সহ। যদি তাইলে দ্রুত হয় তাহলে আপনার বটলনেক লোড সাইজ বা কুয়েরি টাইম; যদি এখনও ধীর থাকে, রেন্ডারিং, ফরম্যাটিং, এবং প্রতি-সারি কম্পোনেন্ট দেখুন।
উদাহরণ: একটি ইনটারনাল Orders স্ক্রিন টাইপ করলে ধীর মনে হলে API 5,000 সারি রিটার্ন করে এবং ব্রাউজার প্রতি কী-প্রেসে সেগুলো ফিল্টার করছে—তাহলে টাইপিং ল্যাগ করবে। অন্যদিকে যদি API 2 সেকেন্ড নেয় কারণ COUNT কুয়েরি অন-ইন্ডেক্সড ফিল্টারে, আপনি কোনো সারি পরিবর্তনের আগে অপেক্ষা দেখবেন। বিভিন্ন ফিক্স, একই ব্যবহারকারী অভিযোগ।
ব্রাউজার প্রায়ই প্রথম বটলনেক। API দ্রুত করলেও পেজ ধীর মনে হতে পারে যদি এটি অনেক পেইন্ট করার চেষ্টায় থাকে। প্রথম নিয়ম: একসঙ্গে হাজার হাজার সারি DOM-এ রেন্ডার করবেন না।
পূর্বে পূর্ণ ভার্চুয়ালাইজেশন যোগ করার আগেই প্রতিটি সারি হালকা রাখুন। নেস্টেড র্যাপার, আইকন, টুলটিপ এবং প্রতিটি সেলে জটিল কন্ডিশনাল স্টাইল থাকলে প্রতিটি স্ক্রল ও আপডেটে খরচ বেড়ে যায়। সাধারণ টেক্সট, কয়েকটি ছোট ব্যাজ, এবং প্রতি সারিতে এক বা দুইটি ইন্টারঅ্যাকটিভ উপাদান রাখাই ভালো।
স্থিতিশীল সারি উচ্চতা ভাবের চেয়েও বেশি কাজে লাগে। যখন প্রতিটি সারি একই উচ্চতার, ব্রাউজার লেআউট প্রেডিক্ট করতে পারে এবং স্ক্রল মসৃণ থাকে। ভ্যারিয়েবল-হাইট সারি (র্যাপিং বর্ণনা, এক্সপ্যান্ডিং নোট, বড় অবতার) অতিরিক্ত মেজারিং ও রিফ্লো ট্রিগার করে। অতিরিক্ত ডিটেইল দরকার হলে সাইড প্যানেল বা একক এক্সপ্যান্ডেবল এরিয়া বিবেচনা করুন, পূর্ণ মাল্টি-লাইন সারির বদলে।
ফরম্যাটিংও চুপিচুপি খরচ বাড়ায়। ডেট, কারেন্সি, ও জটিল স্ট্রিং কাজ বারবার করা হলে খরচ জমে যায়।
যদি একটি মান দেখা না যায়, তা এখনই গণনা করবেন না। ব্যয়বহুল ফরম্যাটিং ফলাফল ক্যাশ করুন এবং চাহিদা অনুযায়ী গণনা করুন—যেমন সারি দৃশ্যমান হলে বা ইউজার সারি খুললে।
কিছু দ্রুত পাস যা প্রায়ই লক্ষণীয় উন্নতি দেয়:
উদাহরণ: একটি ইনওয়াইস টেবিল যেটা ১২টি কলামের কারেন্সি ও তারিখ ফরম্যাট করে, স্ক্রলে স্টাটার করবে। প্রতিটি ইনভয়েসের জন্য ফরম্যাটেড মানগুলো ক্যাশ করলে ও অফ-স্ক্রিন সারিগুলোর কাজ বিলম্ব করলে এটি তৎক্ষণাত মনে হতে পারে, গভীর ব্যাকএন্ড কাজ করার আগেই।
ভার্চুয়ালাইজেশন মানে টেবিল কেবল সেই সারিগুলো আঁকে যা আপনি আসলে দেখতে পারেন (এবং উপরে-নিচে একটু বাফার)। আপনি স্ক্রল করলে একই DOM উপাদানগুলো পুনঃব্যবহার করে ডেটা বদলায়। এর ফলে ব্রাউজার দশ হাজারের বেশি রো কম্পোনেন্ট একসাথে পেইন্ট করার চেষ্টা করে না।
যখন লম্বা তালিকা, চওড়া টেবিল বা ভারী সারি (অবতার, স্ট্যাটাস চিপ, অ্যাকশন মেনু, টুলটিপ) থাকে তখন ভার্চুয়ালাইজেশন উপযুক্ত। যেসব ইউজার প্রচুর স্ক্রল করেন এবং পেজ বাই পেজের বদলে অবিচ্ছিন্ন ভিউ প্রত্যাশা করেন তাদের জন্যও এটা জরুরি।
এটি ম্যাজিক নয়। কয়েকটি জিনিস অবাক করে দিতে পারে:
সবচেয়ে সহজ পথ হলো বোরিং: নির্দিষ্ট সারি উচ্চতা, পূর্বানুমানযোগ্য কলাম, এবং প্রতি সারির ভেতরে অত্যধিক ইন্টারঅ্যাকটিভ উইজেট না রাখা।
দুটো মিলিয়ে ব্যবহার করা যায়: সার্ভার থেকে কী আনবেন তা সীমিত করতে পেজিং (বা কার্সর-ভিত্তিক লোড মোর) ব্যবহার করুন, এবং সেই ফেচ করা স্লাইসের ভিতরে রেন্ডারিং সস্তা রাখতে ভার্চুয়ালাইজেশন ব্যবহার করুন।
প্র্যাকটিক্যাল প্যাটার্ন: একটি স্বাভাবিক পেজ সাইজ (সাধারণত ১০০ থেকে ৫০০ সারি) ফেচ করুন, ঐ পেজের ভিতরে ভার্চুয়ালাইজ করুন, এবং স্পষ্ট কন্ট্রোল দিন পেজ বদলানোর জন্য। ইনফিনাইট স্ক্রল ব্যবহার করলে একটি দৃশ্যমান "Loaded X of Y" সূচক দিন যাতে ব্যবহারকারী বুঝতে পারে তারা সব দেখছে না।
ডেটা বাড়ার সঙ্গে তালিকা ব্যবহারযোগ্য রাখতে হলে, পেজিং সাধারণত নিরাপদ ডিফল্ট। এটি অনিশ্চিত নয়, অ্যাডমিন ওয়র্কফ্লোর জন্য ভালো কাজ করে (রিভিউ, এডিট, অ্যাপ্রুভ) এবং সাধারণ চাহিদাগুলো সমর্থন করে যেমন "এই ফিল্টারে পেজ ৩ এক্সপোর্ট করা"। অনেক দল ইনফিনাইট স্ক্রল চেষ্টা করার পরে আবার পেজিং-এ ফিরে আসে।
ইনফিনাইট স্ক্রল কজবলে সুন্দর মনে হতে পারে অনানুষ্ঠানিক ব্রাউজিং-এ, কিন্তু এর লুকানো খরচ আছে। মানুষ তাদের অবস্থান হারায়, ব্যাক বাটন প্রায়ই একই স্থানে ফিরায় না, এবং দীর্ঘ সেশন মেমরি জমা করে। মধ্যপন্থা হলো Load more বাটন যা এখনও পেজ ব্যবহার করে, তাই ব্যবহারকারী অবস্থান বুঝতে পারে।
Offset পেজিং ক্লাসিক page=10&size=50 পদ্ধতি। এটি সহজ, কিন্তু বড় টেবিলে ধীর হতে পারে কারণ DB-কে পরে থাকা পেজে পৌঁছাতে অনেক সারি স্কিপ করতে হতে পারে। এটি নতুন সারি আসলে আইটেমগুলো পেজের মধ্যে সরে যাওয়ার মত অনুভব করাতে পারে।
Keyset পেজিং (সাধারণত কার্সর পেজিং বলা হয়) বলে "শেষ দেখা আইটেমের পরে পরের ৫০ সারি," সাধারণত id বা created_at ব্যবহার করে। এটি দ্রুত থাকে কারণ এটি সেইসব বড় স্কিপ এড়ায়।
প্রায়োগিক নিয়ম:
ব্যবহারকারীরা মোট ফলাফল দেখতে পছন্দ করে, কিন্তু পুরো "কাউন্ট সব মিলিয়ে" কুয়েরি ভারী ফিল্টারের সঙ্গে ব্যয়বহুল হতে পারে। বিকল্পগুলির মধ্যে জনপ্রিয় ফিল্টারের জন্য কাউন্ট ক্যাশ করা, পেজ লোড হওয়ার পরে ব্যাকগ্রাউন্ডে কাউন্ট আপডেট করা, অথবা আনুমানিক কাউন্ট দেখানো (উদাহরণ: "10,000+") অন্তর্ভুক্ত।
উদাহরণ: একটি Orders স্ক্রিন keyset পেজিং দিয়ে ফলাফল তৎক্ষণাত দেখাতে পারে, তারপর ব্যবহারকারী যখন ফিল্টার থামায় তখন ব্যাকগ্রাউন্ডে সঠিক মোটটি পূরণ করতে পারে।
Koder.ai-তে এটা বানালে, পেজিং ও কাউন্ট আচরণকে স্ক্রিন স্পেসিফিকেশনের অংশ হিসেবে শুরুতেই বিবেচনা করুন যাতে জেনারেট হওয়া ব্যাকএন্ড কুয়েরি ও UI স্টেট পরে একে অপরের সাথে সংঘর্ষ না করে।
অধিকাংশ লিস্ট স্ক্রিন ধীর লাগে কারণ তারা প্রথমেই সবকিছু খোলা রাখে: সব লোড করে, তারপর ব্যবহারকারীকে সঙ্কীর্ণ করতে বলে। এটাকে উল্টো করুন। ব্যবহারিক ডিফল্ট সেট দিয়ে শুরু করুন যা ছোট, ব্যবহারযোগ্য সেট ফেরত দেয় (যেমন: গত ৭ দিন, My items, Status: Open), এবং "All time" কে স্পষ্ট পছন্দ বানান।
টেক্সট সার্চ একটি সাধারণ ফাঁদ। যদি আপনি প্রতিটি কী-স্ট্রোক-এ কুয়েরি চালান, তাহলে অনুরোধের ব্যাকলগ বানাবেন এবং UI ঝলসে উঠবে। সার্চ ইনপুট ডিবাউন্স করুন যাতে ব্যবহারকারী বিরত নিলে শুধু তখনই কুয়েরি পাঠান, এবং নতুন অনুরোধ শুরু হলে পুরনো রিকোয়েস্ট বাতিল করুন। সহজ নিয়ম: যদি ব্যবহারকারী এখনও টাইপ করছে, সার্ভারকে না ডাকুন।
ফিল্টার দ্রুত বোধ করার জন্য স্পষ্টও হতে হবে। টেবিলের উপরে ফিল্টার চিপ দেখান যাতে ব্যবহারকারী দেখতে পায় কি সক্রিয় আছে এবং এক ক্লিকে সরাতে পারে। চিপ লেবেলগুলো মানবসম্মত রাখুন, কাঁচা ফিল্ড নাম নয় (উদাহরণ: Owner: Sam এর পরিবর্তে owner_id=42 না দেখান)। যখন কেউ বলে "আমার ফলাফল অদৃশ্য হয়ে গেছে," বেশিরভাগ ক্ষেত্রেই সেটা অদৃশ্য একটি ফিল্টার।
কিছু প্যাটার্ন যা বড় তালিকাগুলোকে প্রতিশ্রুতিবদ্ধ রাখে:
Saved views নীরব নায়ক। প্রতিটি বার ব্যবহারকারীকে নিখুঁত এক-অফ ফিল্টার বানাতে শেখানোর বদলে তাদের কিছু প্রিসেট দিন যা বাস্তব ওয়ার্কফ্লো মিলে যায়। অপস টিম হয়তো "Failed payments today" এবং "High-value customers" এর মধ্যে দ্রুত সুইচ করবে—এইগুলো এক ক্লিকে পাওয়া যাবে এবং ব্যাকএন্ডেও দ্রুত রাখা সহজ।
আপনি যদি একটি চ্যাট-ড্রিভেন বিল্ডার যেমন Koder.ai-তে ইন্টারনাল টুল বানান, ফিল্টারগুলোকে প্রোডাক্ট ফ্লো-এর অংশ হিসেবে বিবেচনা করুন, একটি বোল্ট-অন হিসেবে নয়। সাধারণ প্রশ্নগুলো থেকে শুরু করুন, তারপর ডিফল্ট ভিউ ও সেভড ভিউগুলি সেই অনুযায়ী ডিজাইন করুন।
লিস্ট স্ক্রিন সাধারণত ডিটেইল পেজের মতো একই ডেটা চায় না। যদি আপনার API প্রতিটি রেকর্ডের সবকিছু রিটার্ন করে, আপনি দুইবারই পেই করবেন: ডাটাবেসে বেশি কাজ এবং ব্রাউজারে বেশি ডেটা পড়া ও রেন্ডার করা। কোয়েরি শেইপিং হল তালিকার জন্য ঠিক তখনই যা দরকার তা চাওয়ার অভ্যাস।
শুরুতে কেবল সেই কলামগুলো রিটার্ন করুন যেগুলো প্রতিটি সারি রেন্ডার করতে প্রয়োজন। বেশিরভাগ ড্যাশবোর্ডে সেটা একটি id, কয়েকটি লেবেল, স্ট্যাটাস, একজন মালিক, এবং টাইমস্ট্যাম্প। বড় টেক্সট, JSON ব্লব, এবং কম্পিউটেড ফিল্ডগুলো অপেক্ষা করতে পারে যতক্ষণ না ব্যবহারকারী সারি খুলে।
প্রথম পেইন্টের জন্য ভারী জয়েন এড়ান। জয়েন সব ঠিক থাকলে ঠিক আছে কিন্তু কয়েকটি টেবিল জয়েন করে এবং তারপর জয়েন করা ডেটার উপর সাজানো বা ফিল্টার করলে ব্যয়বহুল হয়। সাধারণ প্যাটার্ন: তালিকাটি এক টেবিল থেকে দ্রুত নিয়ে আসুন, তারপর সম্পর্কিত ডিটেইল অন-ডিমান্ড লোড করুন (অথবা দৃশ্যমান সারিগুলোর জন্য ব্যাচ-লোড করুন)।
সাজানোর অপশনগুলো সীমিত রাখুন এবং ইনডেক্স করা কলামগুলোর উপর সাজান। "সব কিছু দিয়ে সাজাও" সাহায্যকারী শোনালেও বড় ডেটাসেটে ধীর সেট করতে বাধ্য করে। কয়েকটি পূর্বানুমানযোগ্য বিকল্প রাখুন যেমন created_at, updated_at, বা status, এবং নিশ্চিত করুন ঐ কলামগুলো ইনডেক্স করা আছে।
সার্ভার-সাইড অ্যাগ্রিগেশন নিয়ে সতর্ক থাকুন। বড় ফিল্টার করা সেটে COUNT(*), বিস্তৃত কলামে DISTINCT, বা মোট পেজ গণনা আপনার রেসপন্স টাইম দখল করে ফেলতে পারে।
প্রায়োগিক পন্থা:
COUNT ও DISTINCT অপশনাল ধরুন; সম্ভব হলে ক্যাশ বা আনুমানিক মান দেখানআপনি যদি Koder.ai-এ ইন্টারনাল টুল বানান, প্ল্যানিং মোডে লাইটওয়েট লিস্ট কুয়েরি আলাদাভাবে ডিফাইন করুন যাতে UI ডেটা বৃদ্ধির সঙ্গে ততক্ষণই স্ন্যাপি থাকে।
যদি আপনি চান 100k সারি-এ লিস্ট স্ক্রিন দ্রুত থাকে, ডাটাবেসকে প্রতি রিকোয়েস্টে কম কাজ করাতে হবে। বেশিরভাগ ধীর তালিকা "অতি ডেটা" নয়—এগুলো ভুল ডেটা অ্যাক্সেস প্যাটার্ন।
প্রথমে সেগুলো ইনডেক্স করুন যেগুলো ব্যবহারকারী বাস্তবে বেশি ব্যবহার করে। যদি আপনার তালিকা সাধারণত status দিয়ে ফিল্টার করে এবং created_at দিয়ে সাজায়, তখন সেই অনুযায়ী ইনডেক্স চাই—নাহলে ডাটাবেস অনেক বেশি সারি স্ক্যান করে পরে তা সাজাবে, যা দ্রুত ব্যয়বহুল হয়।
সাধারণ ফিক্স যেগুলো বড় উন্নতি দেয়:
tenant_id, status, created_at)।OFFSET পেজের পরিবর্তে keyset (cursor) পেজিং ব্যবহার করুন। OFFSET ডাটাবেসকে অনেক সারি পেরিয়ে যেতে বাধ্য করে।সহজ উদাহরণ: একটি Orders টেবিল যেখানে কাস্টমার নাম, স্ট্যাটাস, এমাউন্ট, এবং তারিখ দেখাতে চান—লিস্ট ভিউতে প্রতিটি অর্ডার নোট বা সব সম্পর্কিত টেবিল জয়েন করবেন না। কেবল টেবিলে ব্যবহৃত কলামগুলো ফেরত দিন, বাকিগুলো আলাদা রিকোয়েস্টে লোড করুন।
Koder.ai’র মতো প্ল্যাটফর্মে বানালে এই মনোভাব বজায় রাখুন—UI চ্যাট থেকে জেনারেট হলেও নিশ্চিত করুন জেনারেট করা API এন্ডপয়েন্টগুলো কার্সর পেজিং ও সিলেকটিভ ফিল্ড সমর্থন করে, যাতে টেবিল বাড়লেও ডাটাবেস কাজ পূর্বানুমানযোগ্য থাকে।
যদি একটি লিস্ট পেজ আজ ধীর মনে করে, সবকিছু রিইনরাইট করা শুরু করবেন না। প্রথমে নরমাল ইউজ কেস কী তা লক করুন, তারপর সেই পথ অপটিমাইজ করুন।
ডিফাইন করুন ডিফল্ট ভিউ। ডিফল্ট ফিল্টার, সাজানো এবং দৃশ্যমান কলাম নির্ধারণ করুন। লিস্টগুলো সবকিছু দেখানোর চেষ্টা করলে ধীর হয়।
আপনার ব্যবহার অনুযায়ী পেজিং স্টাইল বেছে নিন। যদি ইউজাররা বেশিরভাগই প্রথম কয়েক পেজ স্ক্যান করেন, ক্লাসিক পেজিং ঠিক আছে। যদি মানুষ গভীরে ঝাঁপায় (পেজ 200+), বা স্থির পারফরম্যান্স দরকার, keyset পেজিং ব্যবহার করুন (created_at+id মতো স্থিতিশীল সাজানো)।
টেবিল বডির জন্য ভার্চুয়ালাইজেশন যোগ করুন। ব্যাকএন্ড দ্রুত হলেও ব্রাউজার অতিরিক্ত সারি রেন্ডার করলে ব্যর্থ হতে পারে।
সার্চ ও ফিল্টার দ্রুত মনে করান। টাইপিং ডিবাউন্স করুন যাতে প্রতিটি কী-স্ট্রোক-এ রিকোয়েস্ট না যায়। ফিল্টার স্টেট URL-এ বা একক শেয়ার্ড স্টেট স্টোরে রাখুন যাতে রিফ্রেশ, ব্যাক বাটন এবং ভিউ শেয়ারিং নির্ভরযোগ্য থাকে। শেষ সফল রেজাল্ট ক্যাশ করুন যাতে টেবিল খালি ঝলসে না ওঠে।
মাপুন, তারপর কুয়েরি ও ইনডেক্স টিউন করুন। সার্ভার টাইম, ডাটাবেস টাইম, পেআউড সাইজ, এবং রেন্ডার টাইম লগ করুন। তারপর কুয়েরি ছাঁকুন: কেবল সারিগুলোতে দেখানো কলাম সিলেক্ট করুন, ফিল্টার আগে প্রয়োগ করুন, এবং ডিফল্ট ফিল্টার+সাজানোর মতো ইনডেক্স যোগ করুন।
উদাহরণ: একটি সাপোর্ট ড্যাশবোর্ড যার 100k টিকেট আছে—ডিফল্টভাবে Open, আমার টিম-এ অ্যাসাইনড, নবীন থেকে পুরোনো সাজানো, ছয়টি কলাম দেখান, এবং কেবল ticket id, subject, assignee, status, এবং timestamps ফেচ করুন। keyset পেজিং ও ভার্চুয়ালাইজেশনের সঙ্গে ডাটাবেস ও UI দুইই পূর্বানুমানযোগ্য থাকবে।
Koder.ai-এ এটি বানালে, এই পরিকল্পনা ইটারেট-এন্ড-চেক ওয়ার্কফ্লোতে ভাল মানায়: ভিউ অ্যাডজাস্ট করুন, স্ক্রল ও সার্চ টেস্ট করুন, তারপর কুয়েরি টিউন করে দেখুন পেজ টিকে স্ন্যাপি আছে কি না।
100k সারিকে সাধারণ পেজ ডেটা মনে করলে লিস্ট স্ক্রিন ভাঙিয়ে ফেলার দ্রুত উপায়। বেশিরভাগ ধীর ড্যাশবোর্ডে কয়েকটি পূর্বানুমানযোগ্য ফাঁদ থাকে।
একটি বড় ফাঁদ হল সবকিছু রেন্ডার করে CSS দিয়ে হাইড করা। ভিভ্যুতে কেবল ৫০ই দৃশ্যমান মনে হলেও, ব্রাউজার 100k DOM নোড তৈরি, মেজার এবং স্ক্রলে রেপেইন্টের জন্য খরচ করে। দীর্ঘ তালিকা হলে কেবল দেখা যা রেন্ডার করুন (ভার্চুয়ালাইজেশন) এবং সারি কম্পোনেন্টগুলো সিম্পল রাখুন।
সার্চও ধীরে ধীরে পারফরম্যান্স নষ্ট করে যখন প্রতিটি কী-স্ট্রোক একটি পুরো টেবিল স্ক্যান ট্রিগার করে। এটা হয় যখন ফিল্টারগুলো ইনডেক্স-বিহীন, আপনি অনেক কলামে সার্চ করছেন, বা বিশাল টেক্সট ফিল্ডে contains কুয়েরি চালান বিনা পরিকল্পনার। ভাল নিয়ম: ব্যবহারকারীর প্রথম ফিল্টারটি ডাটাবেসে সস্তা হওয়া উচিত, কেবল UI-এ সুবিধাজনক না।
অপর একটি সাধারণ সমস্যা হল লিস্টে পুরো রেকর্ড ফেচ করা যখন সারি কেবল সারসংক্ষেপ হয়। একটি লিস্ট সারি সাধারণত ৫–১২ ফিল্ডই চায়, পুরো অবজেক্ট, দীর্ঘ বর্ণনা, বা সম্পর্কিত ডেটা না। অতিরিক্ত ডেটা টানা ডাটাবেস কাজ, নেটওয়ার্ক টাইম, এবং ফ্রন্টএন্ড পার্সিং বাড়ায়।
এক্সপোর্ট ও মোট হিসাব যদি মূল থ্রেডে করা হয় বা ভারী রিকোয়েস্টের জন্য অপেক্ষা করা হয়, UI ফরজ হতে পারে। UI প্রতিক্রিয়াশীল রাখুন: এক্সপোর্ট ব্যাকগ্রাউন্ডে শুরু করুন, প্রগতি দেখান, এবং প্রতিটি ফিল্টার বদলালে মোট পুনরায় গণনা এড়িয়ে চলুন।
অবশেষে, খুব বেশি সাজানোর অপশন সমস্যা তৈরি করে। যদি ইউজার সব কলাম অনুযায়ী সাজাতে পারে, আপনি বড় রেজাল্ট সেটগুলোর উপর মেমরি-ভিত্তিক সাজানো বা ডাটাবেসকে ধীর প্ল্যান করতে বাধ্য করবেন। সাজোনো সীমিত রাখুন এবং ডিফল্ট সাজানো বাস্তব ইনডেক্সের সাথে মিল রাখুন।
দ্রুত গাট-চেক:
লিস্ট পারফরম্যান্সকে এককালীন টুইক নয়, একটি প্রোডাক্ট ফিচার হিসাবে বিবেচনা করুন। একটি লিস্ট স্ক্রিন তখনই দ্রুত যখন বাস্তব মানুষরা স্ক্রল, ফিল্টার, ও সাজানো করলে তা দ্রুত মনে হয়।
এই চেকলিস্ট ব্যবহার করে নিশ্চিত করুন আপনি সঠিক জিনিসগুলো ঠিক করেছেন:
সহজ বাস্তবতা পরীক্ষা: লিস্ট খুলুন, 10 সেকেন্ড স্ক্রল করুন, তারপর একটি সাধারণ ফিল্টার (যেমন Status: Open) প্রয়োগ করুন। যদি UI ফ্রিজ করে, সমস্যা সাধারণত রেন্ডারিং (অতিরিক্ত DOM সারি) বা প্রতিটি আপডেটে হওয়া ভারী ক্লায়েন্ট-সাইড ট্রান্সফর্ম (সাজানো, গ্রুপিং, ফরম্যাটিং) হয়।
পরবর্তী পদক্ষেপ, ক্রমে, যাতে আপনি ফিক্সের মধ্যে না লাফান:
আপনি যদি Koder.ai (koder.ai) দিয়ে এটি বানান, Planning Mode-এ শুরু করুন: প্রথমে সঠিক লিস্ট কলাম, ফিল্টার ক্ষেত্র, এবং API রেসপন্স শেইপ নির্ধারণ করুন। তারপর স্ন্যাপশট ও রোলব্যাক ব্যবহার করে ইটারেট করুন যখন কোনো পরীক্ষা স্ক্রিন ধীর করে।
শুরুতেই লক্ষ্য বদলান: “সব কিছু লোড করা” থেকে “প্রথম অনুপযোগী সারিগুলো দ্রুত দেখানো”। সময়কে প্রথম সারি দেখানোর দিকে অপটিমাইজ করুন এবং যে ক্রিয়াগুলোই করা হোক—ফিল্টার, সাজানো, স্ক্রলিং—সেগুলো মসৃণ রাখুন, যদিও পুরো ডেটাসেট একবারে লোড করা না হয়।
লোড বা ফিল্টার বদলানোর পর প্রথম সারি দেখতে কতক্ষণ লাগে, ফিল্টার/সাজানো আপডেট হওয়া কতোক্ষণ নেয়, রেসপন্স পেআউডের আকার, ধীর ডাটাবেস কুয়েরি (বিশেষ করে COUNT(*) এবং বিস্তৃত SELECT), এবং ব্রাউজারের মেইন-থ্রেড স্পাইক—এইগুলো মাপুন। এগুলোই ব্যবহারকারী যে ল্যাগ অনুভব করছে তার সঙ্গে সরাসরি সম্পর্কিত।
সরল পরীক্ষা: ব্যাকএন্ডকে সাময়িকভাবে একই ফিল্টার আর সাজানো রেখে কেবল 20টি সারি রিটার্ন করতে বলুন। দ্রুত হলে জট বা পে-লোড বড় হওয়া বা কুয়েরি টাইম সমস্যা; এখনও ধীর হলে রেন্ডারিং, ফরম্যাটিং বা প্রতি সারির ক্লায়েন্ট-সাইড কাজ দেখুন।
একেবারে সহজ পরিবর্তনগুলি: হাজার হাজার সারি DOM-এ রাখা বন্ধ করুন, সারি কম্পোনেন্টগুলো সিম্পল রাখুন, এবং সারির উচ্চতা স্থির রাখুন। অফ-স্ক্রিন সারির ফরম্যাটিং এখনই করবেন না—দেখার সময় বা সারি খুললে গণনা করুন এবং ফলাফল ক্যাশ করুন।
ভার্চুয়ালাইজেশন কেবল সেই সারিগুলো রেন্ডার করে দেখায় যেগুলো দৃশ্যমান (সামান্য বাফারসহ)। এটি তখনই উপকার করে যখন ইউজার অনেক স্ক্রল করে বা সারিগুলো ভারী। তবে কনসিসটেন্ট রো-উচ্চতা না থাকলে, স্টিকি হেডার/কলাম বা কীবোর্ড নাভিগেশনের ক্ষেত্রে জটিলতা দেখা দিতে পারে।
অ্যাডমিন/ইন্টারনাল ওয়ার্কফ্লো-এ সাধারণত পেজিং নিরাপদ ডিফল্ট। এটি ব্যবহারকারীকে অবস্থান বুঝতে সাহায্য করে এবং সার্ভার কাজ সীমিত রাখে। ইনফিনাইট স্ক্রল হালকা ব্রাউজিংয়ে ঠিকে পারে, কিন্তু নেভিগেশন ও মেমরি সমস্যা বাড়ায়—মাঝাপথীয় সমাধি হলো Load more বাটন।
Offset পেজিং (page=10&size=50) সহজ, কিন্তু বড় টেবিলে গভীরে গেলে ধীর হতে পারে কারণ DB-কে অনেক সারি স্কিপ করতে হয়। Keyset (cursor) পেজিং — “শেষ দেখা আইটেমের পরে পরের 50” — সাধারণত দ্রুত থাকে কারণ এটি বড় স্কিপ এড়ায়।
প্রতিটি কি-স্ট্রোক-এ সার্ভারে কুয়েরি না পাঠান। সার্চ ইনপুট ডিবাউন্স করুন এবং নতুন অনুরোধ আসলে পুরনো অনুরোধ বাতিল করুন। ডিফল্টভাবে সংকীর্ণ ফিল্টার দিন (যেমন: শেষ ৭ দিন, My items, Status: Open) যেন প্রথম কুয়েরি ছোট ও ব্যবহারযোগ্য হয়।
লিস্ট API থেকে কেবলই সেই ফিল্ডগুলো ফিরিয়ে দিন যেগুলো তালিকাতে দেখান—সাধারণত id, লেবেল, স্ট্যাটাস, মালিক, এবং টাইমস্ট্যাম্প। বড় টেক্সট, JSON ব্লব এবং সম্পর্কিত ডেটা আলাদা ডিটেইল রিকোয়েস্টে রাখুন যেন প্রথম পেইন্ট হালকা থাকে।
প্রাথমিক ফিল্টার এবং সাজানো ব্যবহারিক কেস ঠিক করে সেই অনুসারে ইনডেক্স দিন—প্রায়শই কম্পোজিট ইনডেক্স দরকার। COUNT বা DISTINCT মতো অপারেশন ব্যয়বহুল; এগুলো ক্যাশ, ব্যাকগ্রাউন্ডে পূরণ বা আনুমানিক সংখ্যা দেখানোর বিকল্প রাখুন। সারি পাতলা রাখুন: লিস্ট ভিউতে বড় ফিল্ড, JSON ব্লব বা নোট না নিন।