এসকিউএল সার্ভারের BULK INSERTকমান্ডটি ব্যবহার করে আমি কিছু বরং পুরানো কোডটি আবার লিখতে চলেছি কারণ স্কিমাটি বদলে গেছে, এবং এটি আমার কাছে ঘটেছে যে পরিবর্তে কোনও টিভিপি দিয়ে কোনও সঞ্চিত পদ্ধতিতে স্যুইচ করার বিষয়ে আমার ভাবনা উচিত, তবে আমি ভাবছি কী প্রভাব ফেলবে এটি পারফরম্যান্সে থাকতে পারে।
কিছু ব্যাকগ্রাউন্ড তথ্য যা আমি এই প্রশ্নটি জিজ্ঞাসা করছি তা ব্যাখ্যা করতে সহায়তা করতে পারে:
ডেটা আসলে একটি ওয়েব পরিষেবার মাধ্যমে আসে। ওয়েব সার্ভিস ডাটাবেস সার্ভারে একটি ভাগ করা ফোল্ডারে একটি পাঠ্য ফাইল লিখে যা ফলস্বরূপ একটি সম্পাদন করে
BULK INSERT। এই প্রক্রিয়াটি মূলত এসকিউএল সার্ভার 2000 এ বাস্তবায়িত হয়েছিল এবং সেই সময়INSERTসার্ভারে কয়েক শ'টি বক্তব্য চক করা ব্যতীত অন্য কোন বিকল্প ছিল না , যা আসলে আসল প্রক্রিয়া ছিল এবং কার্য সম্পাদনের বিপর্যয় ছিল।ডেটাটি একটি স্থায়ী মঞ্চের টেবিলে বাল্কটি inোকানো হয় এবং তারপরে একটি আরও বড় টেবিলের সাথে একীভূত হয় (যার পরে এটি স্টেজিং টেবিল থেকে মুছে ফেলা হয়)।
তথ্য সন্নিবেশ করতে পরিমাণ "বড়", তবে "বিশাল" নয় - সাধারণত কয়েকশো সারি, বিরল দৃষ্টান্তে 5-10k সারি শীর্ষে থাকে। অতএব আমার অন্ত্র অনুভূতি হ'ল
BULK INSERTএকটি লগ-লগ করা অপারেশন হওয়া এই বড় কোনও পার্থক্য আনবে না (তবে অবশ্যই আমি নিশ্চিত নই, সুতরাং প্রশ্ন)।সন্নিবেশটি আসলে একটি বৃহত্তর পাইপলাইন ব্যাচ প্রক্রিয়াটির অংশ এবং একের পর এক বহুবার ঘটতে হবে; অতএব কর্মক্ষমতা হয় সমালোচনামূলক।
যে কারণগুলিকে আমি BULK INSERTটিভিপি দিয়ে প্রতিস্থাপন করতে চাই তা হ'ল:
নেটবিআইওএস-এর মাধ্যমে টেক্সট ফাইলটি লেখার জন্য ইতিমধ্যে কিছুটা সময় ব্যয় হয়েছে এবং এটি কোনও স্থাপত্যের দৃষ্টিকোণ থেকে বেশ মারাত্মক।
আমি বিশ্বাস করি যে মঞ্চের টেবিলটি (এবং হওয়া উচিত) নির্মূল করা যেতে পারে। এটির মূল কারণ হ'ল dataোকানো ডেটা একই সময়ে সন্নিবেশের সময় অন্যান্য কয়েকটি আপডেটের জন্য ব্যবহার করা প্রয়োজন এবং প্রায় খালি মঞ্চায়ন করার চেয়ে বিশাল উত্পাদন সারণী থেকে আপডেটটি অর্জন করা অনেক ব্যয়বহুল lier টেবিল একটি TVP সঙ্গে, পরামিতি মূলত হয় উপস্থাপনকারী টেবিল, আমি কিচ্ছু আমি আগে সাথে করতে চান / মূল সন্নিবেশ পর এটা করতে পারেন।
আমি ডুপ-চেকিং, ক্লিনআপ কোড এবং বাল্ক সন্নিবেশগুলির সাথে সম্পর্কিত ওভারহেডের সমস্ত কিছু সরিয়ে ফেলতে পারি।
যদি সার্ভারটি একবারে এই লেনদেনগুলির মধ্যে কয়েকটি পেয়ে যায় তবে স্টেজিং টেবিল বা টেম্পডিবিতে লক কনটেন্ট নিয়ে উদ্বেগের দরকার নেই (আমরা এটি এড়াতে চেষ্টা করি, তবে এটি ঘটে)।
আমি অবশ্যই প্রোডাক্টে কিছু দেওয়ার আগে এটির প্রোফাইল দিতে চলেছি, তবে আমি ভেবেছিলাম যে এই সমস্ত সময় ব্যয় করার আগে প্রথমে জিজ্ঞাসা করা ভাল ধারণা হতে পারে, এই উদ্দেশ্যে টিভিপি ব্যবহারের বিষয়ে কারও কাছে কোনও কঠোর সতর্কতা রয়েছে কিনা তা দেখুন।
সুতরাং - যে কেউ এসকিউএল সার্ভার ২০০৮ এর সাথে যথেষ্ট স্বাচ্ছন্দ্য বোধ করেন তিনি চেষ্টা করেছেন বা কমপক্ষে এটি তদন্ত করেছেন, রায় কী? Sayোকানোর জন্য, ধরা যাক, কয়েকশ থেকে কয়েক হাজার সারি, প্রায়শই ঘন ঘন ভিত্তিতে ঘটছে, টিভিপিগুলি কি সরিষা কাটবে? বাল্ক সন্নিবেশগুলির তুলনায় পারফরম্যান্সে কি উল্লেখযোগ্য পার্থক্য রয়েছে?
আপডেট: এখন 92% কম প্রশ্ন চিহ্ন সহ!
(একে: পরীক্ষার ফলাফল)
36-পর্যায়ের স্থাপনার প্রক্রিয়াটির মতো অনুভব করার পরে শেষ ফলাফলটি এখন উত্পাদনে। উভয় সমাধানের ব্যাপকভাবে পরীক্ষা করা হয়েছিল:
- ভাগ করা-ফোল্ডার কোডটি ছড়িয়ে দেওয়া এবং ব্যবহার করে
SqlBulkCopyক্লাসটি সরাসরি করা; - টিভিপি সহ একটি সঞ্চিত পদ্ধতিতে স্যুইচ করা।
ঠিক তাই পাঠকরা এই তথ্যটির নির্ভরযোগ্যতা সম্পর্কে যে কোনও সন্দেহ দূর করতে, ঠিক কী পরীক্ষা করা হয়েছিল তার একটি ধারণা পেতে পারেন , এই আমদানি প্রক্রিয়াটি আসলে কী করে তার আরও বিস্তারিত ব্যাখ্যা এখানে দেওয়া হয়েছে :
একটি টেম্পোরাল ডেটা সিকোয়েন্স দিয়ে শুরু করুন যা প্রায় 20-50 ডেটা পয়েন্ট (যদিও এটি কখনও কখনও কয়েকশো বেশি হতে পারে) থেকে শুরু করে;
এটিতে পুরো একগুচ্ছ ক্রেজি প্রসেসিং করুন যা বেশিরভাগ ডাটাবেসের চেয়ে আলাদা। এই প্রক্রিয়াটি সমান্তরাল, সুতরাং (1) এর সিকোয়েন্সগুলির প্রায় 8-10 একই সময়ে প্রক্রিয়াজাত করা হচ্ছে। প্রতিটি সমান্তরাল প্রক্রিয়া 3 অতিরিক্ত সিকোয়েন্স তৈরি করে।
সমস্ত 3 টি সিকোয়েন্স এবং আসল সিকোয়েন্স নিন এবং তাদের একটি ব্যাচে সংযুক্ত করুন।
এখন 8-10-সমাপ্ত সমস্ত প্রসেসিংয়ের কাজগুলি থেকে একটি বড় সুপার ব্যাচে বিচগুলি একত্রিত করুন।
BULK INSERTকৌশলটি (পরবর্তী পদক্ষেপ দেখুন), অথবা টিভিপি কৌশল (আট ধাপে এড়িয়ে যান) ব্যবহার করে এটি আমদানি করুন ।SqlBulkCopy4 টি স্থায়ী মঞ্চের টেবিলগুলিতে পুরো সুপার-ব্যাচটি ফেলার জন্য ক্লাসটি ব্যবহার করুন ।সঞ্চিত পদ্ধতি চালান যা (ক) বেশ কয়েকটি
JOINশর্ত সহ টেবিলের ২ টিতে একত্রে একত্রিত করার পদক্ষেপগুলি সম্পাদন করে এবং তারপরে (খ) একটি সম্পাদন করেMERGEএকত্রিত এবং অ-সংগৃহীত ডেটা উভয় ব্যবহার করে production টি উত্পাদন টেবিলের উপর করে। (সমাপ্ত)বা
সংযুক্ত করতে ডেটাযুক্ত 4 টি
DataTableঅবজেক্ট তৈরি করুন ; এর মধ্যে 3 টিতে সিএলআর প্রকার রয়েছে যা দুর্ভাগ্যক্রমে ADO.NET টিভিপিগুলি যথাযথভাবে সমর্থন করে না, তাই তারা স্ট্রিং উপস্থাপনা হিসাবে চালিত হতে হবে, যা পারফরম্যান্সকে কিছুটা ব্যথা দেয়।টিভিপিগুলিকে একটি সঞ্চিত পদ্ধতিতে ফিড দিন, যা মূলত (7) এর মতো একই প্রক্রিয়াজাতকরণ করে তবে সরাসরি প্রাপ্ত টেবিলগুলি দিয়ে। (সমাপ্ত)
ফলাফলগুলি যুক্তিসঙ্গতভাবে নিকটে ছিল, তবে টিভিপি পদ্ধতির পরিশেষে গড়ের চেয়ে আরও ভাল পারফরম্যান্স করা হয়েছিল, এমনকি যখন ডাটা অল্প পরিমাণে 1000 সারি অতিক্রম করে।
নোট করুন যে এই আমদানি প্রক্রিয়াটি পর পর কয়েক হাজার বার চালিত হয়, তাই একীভূতকরণের সমস্ত শেষ করতে কত ঘন্টা (হ্যাঁ, ঘন্টা) লেগেছিল তা গণনা করে গড় গড় পাওয়া খুব সহজ ছিল।
মূলত, একটি গড় মার্জ সম্পূর্ণ হতে প্রায় 8 সেকেন্ড সময় নেয় (সাধারণ বোঝার নীচে)। নেটবিআইওএস কলডেজ সরানো এবং SqlBulkCopyসময়টি প্রায় হ্রাস করে প্রায় 7 সেকেন্ডে স্যুইচ করা । টিভিপিগুলিতে স্যুইচ করা সময়টি প্রতি ব্যাচে সময়কে 5.2 সেকেন্ডে কমিয়ে দেয় । এটি এমন একটি প্রক্রিয়ার জন্য থ্রুপুটটিতে 35% উন্নতি যার চলমান সময়টি কয়েক ঘন্টা পরিমাপ করা হয় - তাই মোটেও খারাপ নয়। এটি একটি 25% ডলার উন্নতিও হয়েছেSqlBulkCopy ।
আমি প্রকৃতপক্ষে যথেষ্ট আত্মবিশ্বাসী যে এর চেয়ে প্রকৃত উন্নতি উল্লেখযোগ্যভাবে বেশি ছিল। পরীক্ষার সময় এটি স্পষ্ট হয়ে যায় যে চূড়ান্ত সংশ্লেষটি আর সমালোচনামূলক পথ নয়; পরিবর্তে, ওয়েব সার্ভিস যা ডেটা প্রসেসিংয়ের সমস্ত কাজ করে যাচ্ছিল অনুরোধের সংখ্যার আওতায় আসার শুরু হয়েছিল। কিছু ক্ষেত্রে আমরা ধারাবাহিকভাবে সংশ্লেষের মধ্যে কয়েকটি অলস সেকেন্ডের ব্যবধানটি দেখছিলাম। সামান্য ব্যবধান ছিল, তবে ব্যবহারের সময় অনেক ছোট (আধ সেকেন্ড বা তার বেশি) SqlBulkCopy। তবে আমি মনে করি এটি অন্য দিনের জন্য গল্প হয়ে উঠবে।
উপসংহার: টেবিল-মূল্যবান প্যারামিটারগুলি BULK INSERTমাঝারি আকারের ডেটা সেটগুলিতে অপারেটিং জটিল আমদানি + ট্রান্সফর্ম প্রক্রিয়াগুলির জন্য অপারেশনগুলির চেয়ে সত্যই কার্য সম্পাদন করে।
আমি অন্য একটি পয়েন্ট যুক্ত করতে চাই, কেবলমাত্র অংশীদারদের পক্ষে যারা অংশীদারদের পক্ষ থেকে কোনও আশঙ্কা প্রকাশ করতে। এক উপায়ে, এই পুরো পরিষেবাটি একটি বিশাল স্টেজেজিং প্রক্রিয়া। প্রক্রিয়াটির প্রতিটি পদক্ষেপের ভারী নিরীক্ষণ করা হয়, সুতরাং কিছু নির্দিষ্ট সংশ্লেষ কেন ব্যর্থ হয়েছিল তা নির্ধারণ করার জন্য আমাদের স্টেজিং টেবিলের প্রয়োজন নেই (যদিও বাস্তবে এটি প্রায় কখনও ঘটে না)। আমাদের যা করতে হবে তা হ'ল পরিষেবাতে একটি ডিবাগ পতাকা সেট করা এবং এটি ডিবাগারে ভেঙে যায় বা ডাটাবেসের পরিবর্তে কোনও ডেটাতে এর ডেটা ফেলে দেয়।
অন্য কথায়, আমাদের ইতিমধ্যে প্রক্রিয়াটির জন্য পর্যাপ্ত অন্তর্দৃষ্টি রয়েছে এবং একটি মঞ্চ টেবিলের সুরক্ষার প্রয়োজন নেই; আমাদের প্রথম স্থানে স্টেজিং টেবিল থাকার একমাত্র কারণ ছিল আমাদের যে বিবৃতি INSERTএবং UPDATEঅন্যথায় আমাদের অন্যথায় ব্যবহার করতে হত সেগুলি সম্পর্কে আঘাত করা এড়ানো । মূল প্রক্রিয়াতে, মঞ্চের ডেটা কেবলমাত্র দ্বিতীয় সেকেন্ডের ভগ্নাংশের জন্য মঞ্চ টেবিলে থাকত, সুতরাং এটি রক্ষণাবেক্ষণ / রক্ষণাবেক্ষণের শর্তাদির কোনও মূল্য যুক্ত করে নি।
আরও মনে রাখবেন যে আমরা প্রতিটি একক অপারেশনকে টিভিপিসহ প্রতিস্থাপন করি নিBULK INSERT । বেশ কয়েকটি ক্রিয়াকলাপ যা বৃহত পরিমাণে ডেটা নিয়ে ডিল করে এবং / অথবা ডিবিতে ফেলে দেওয়া ছাড়া অন্য কোনও ডেটা দিয়ে বিশেষ কিছু করার দরকার পড়ে না SqlBulkCopy। আমি প্রস্তাব দিচ্ছি না যে টিভিপিগুলি একটি পারফরম্যান্স পেনেসিয়া, কেবলমাত্র তারা SqlBulkCopyপ্রাথমিক স্টেজিং এবং চূড়ান্ত একীকরণের মধ্যে বেশ কয়েকটি রূপান্তর জড়িত এই নির্দিষ্ট ক্ষেত্রে সফল হয়েছিল ।
তাই সেখানে যদি আপনি এটি আছে। পয়েন্টটি সর্বাধিক প্রাসঙ্গিক লিঙ্কটি অনুসন্ধানের জন্য টিটোনিতে যায় তবে আমি অন্যান্য প্রতিক্রিয়াগুলিও প্রশংসা করি। আবার ধন্যবাদ!