বিশাল টেবিলের মধ্যে কয়েকটি সারি সন্নিবেশ করানো ধীর পারফরম্যান্স


9

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

স্টোরগুলিতে ডেটা প্রবেশ করানোর সাথে সাথে এই ইনভেন্টরি আপডেট প্রক্রিয়াটি সাধারণত দিনে বহুবার চালিত হয়। এই কয়েকটি স্টোর থেকে আপডেট ডেটা চালায়। তবে, গ্রাহকরা গত 30 দিনের মধ্যে সমস্ত স্টোর আপডেট করার জন্য এটি চালাতে পারেন। এই ক্ষেত্রে, প্রক্রিয়াটি 10 ​​টি থ্রেডকে স্পিন করে এবং প্রতিটি স্টোরের ইনভেস্টরিকে আলাদা থ্রেডে আপডেট করে।

প্রক্রিয়াটি দীর্ঘ সময় নিচ্ছে বলে গ্রাহক অভিযোগ করছেন। আমি প্রক্রিয়াটি প্রোফাইল করে দিয়েছি যে এই সারণিতে INSERT গুলি আমার প্রত্যাশার চেয়ে অনেক বেশি সময় ব্যয় করছে এমন একটি ক্যোয়ারী। এই INSERT কখনও কখনও 30 সেকেন্ডে সম্পূর্ণ হয়।

আমি যখন এই টেবিলের বিপরীতে একটি অ্যাড-হক এসকিউএল ইনসার্ট কমান্ড চালাচ্ছি (শুরু বিগান ট্রান এবং রোলব্যাক দ্বারা বদ্ধ), অ্যাড-হক এসকিউএল মিলি সেকেন্ডের অর্ডারে সম্পূর্ণ হয়।

ধীর পারফর্মিং কোয়েরি নীচে is ধারণাটি রেকর্ডগুলি অন্তর্ভুক্ত করা হয় যা সেখানে নেই এবং পরে আপডেট করার জন্য আমরা বিভিন্ন বিটের ডেটা গণনা করি। প্রক্রিয়াটির পূর্বের পদক্ষেপটি আইটেমগুলি সনাক্ত করেছে যা আপডেট করতে হবে, কিছু গণনা করা হয়েছে, এবং ফলাফলগুলি টেম্প্যাডবি টেবিল আপডেট_আইটেম_ ওয়ার্কে স্টাফ করেছে। এই প্রক্রিয়াটি 10 ​​টি পৃথক থ্রেডে চলছে এবং প্রতিটি থ্রেডের আপডেট_আইটেম_ ওয়ার্কে নিজস্ব জিইউডি রয়েছে।

INSERT INTO Inventory
(
    Inv_Site_Key,
    Inv_Item_Key,
    Inv_Date,
    Inv_BusEnt_ID,
    Inv_End_WtAvg_Cost
)
SELECT DISTINCT
    UpdItemWrk_Site_Key,
    UpdItemWrk_Item_Key,
    UpdItemWrk_Date,
    UpdItemWrk_BusEnt_ID,
    (CASE UpdItemWrk_Set_WtAvg_Cost WHEN 1 THEN UpdItemWrk_WtAvg_Cost ELSE 0 END)
FROM tempdb..Update_Item_Work (NOLOCK)
WHERE UpdItemWrk_GUID = @GUID
AND NOT EXISTS
    -- Only insert for site/item/date combinations that don't exist
    (SELECT *
    FROM Inventory (NOLOCK)
    WHERE Inv_Site_Key = UpdItemWrk_Site_Key
    AND Inv_Item_Key = UpdItemWrk_Item_Key
    AND Inv_Date = UpdItemWrk_Date)

ইনভেন্টরি সারণীতে 42 টি কলাম রয়েছে যার মধ্যে বেশিরভাগ ট্র্যাকের পরিমাণ এবং বিভিন্ন জায়ের সামঞ্জস্যের জন্য গণনা করা হয়। sys.dm_db_index_physical_stats বলছে যে প্রতিটি সারিটি প্রায় 242 বাইট, তাই আমি আশা করি প্রায় একসাথে 8 কেবি পৃষ্ঠায় 33 টি সারি ফিট হবে।

সারণীটি অনন্য বাধা (ইনভাইটসাইট_কি, ইনভ_ আইটেম_কি, ইনভ_ডেট) এ ক্লাস্টার করা হয়েছে। সমস্ত কীগুলি নির্ধারিত (15,0), এবং তারিখটি ছোট AT এখানে একটি আইডেন্টিটি প্রাথমিক কী (অবিচ্ছিন্ন) এবং অন্যান্য 4 টি সূচক রয়েছে। সমস্ত সূচক এবং ক্লাস্টার্ড সীমাবদ্ধতা একটি সুস্পষ্ট (FILLFACTOR = 90, PAD_INDEX = চালু) দিয়ে সংজ্ঞায়িত করা হয়েছে।

পৃষ্ঠা বিভাজনগুলি গণনা করার জন্য আমি লগ ফাইলটিতে দেখলাম। আমি ক্লাস্টারড ইনডেক্সে প্রায় 1,027 বিভক্ত এবং অন্য সূচকে 1,724 বিভাজন পরিমাপ করেছি, তবে কোনটি অন্তরালে ঘটেছে সে সম্পর্কে আমি রেকর্ড করি নি। দেড় ঘন্টা পরে, আমি ক্লাস্টারড ইনডেক্সে 7,035 পৃষ্ঠার বিভাজন পরিমাপ করেছি।

আমি প্রোফাইলারে বন্দী ক্যোয়ারী পরিকল্পনাটি দেখে মনে হচ্ছে:

Rows         Executes     StmtText                                                                                                                                             
----         --------     --------                                                                                                                                             
490          1            Sequence                                                                                                                                             
0            1              |--Index Update
0            1              |    |--Collapse
0            1              |         |--Sort
0            1              |              |--Filter
996          1              |                   |--Table Spool                                                                                                                 
996          1              |                        |--Split                                                                                                                  
498          1              |                             |--Assert
0            0              |                                  |--Compute Scalar
498          1              |                                       |--Clustered Index Update(UK_Inventory)
498          1              |                                            |--Compute Scalar
0            0              |                                                 |--Compute Scalar
0            0              |                                                      |--Compute Scalar
498          1              |                                                           |--Compute Scalar
498          1              |                                                                |--Top
498          1              |                                                                     |--Nested Loops
498          1              |                                                                          |--Stream Aggregate
0            0              |                                                                          |    |--Compute Scalar
498          1              |                                                                          |         |--Clustered Index Seek(tempdb..Update_Item_Work)
498          498            |                                                                          |--Clustered Index Seek(Inventory)
0            1              |--Index Update(UX_Inv_Exceptions_Date_Site_Item)
0            1              |    |--Collapse
0            1              |         |--Sort
0            1              |              |--Filter
996          1              |                   |--Table Spool
490          1              |--Index Update(UX_Inv_Date_Site_Item)
490          1                   |--Collapse
980          1                        |--Sort
980          1                             |--Filter
996          1                                  |--Table Spool                                                                                       

বনাম বিভিন্ন ডিএমভির ক্যোয়ারীগুলিতে তাকিয়ে দেখছি ক্যোরিটি এই ইনভেন্টরি টেবিলের একটি পৃষ্ঠায় 0 পৃষ্ঠার জন্য PAGEIOLATCH_EX এ অপেক্ষা করছে। আমি কোনও অপেক্ষা বা লকগুলিতে ব্লক করতে দেখছি না।

এই মেশিনটির প্রায় 32 গিগাবাইট মেমরি রয়েছে। এটি এসকিউএল সার্ভার 2005 স্ট্যান্ডার্ড সংস্করণ চলছে, যদিও শীঘ্রই তারা 2008 আর 2 এন্টারপ্রাইজ সংস্করণে আপগ্রেড করছে। ডিস্ক ব্যবহারের ক্ষেত্রে ইনভেন্টরি টেবিলটি কত বড় সে সম্পর্কে আমার সংখ্যা নেই, তবে প্রয়োজনে আমি তা পেতে পারি। এটি এই সিস্টেমের বৃহত্তম টেবিলগুলির মধ্যে একটি।

আমি sys.dm_io_virtual_file_stats এর বিপরীতে একটি ক্যোয়ারী চালিয়েছি এবং গড় লেখার জন্য টেম্পডিবির বিপরীতে 1.1 সেকেন্ডের উপরে অপেক্ষা করতে দেখছি । এই টেবিলটি যে ডেটাবেসটিতে সঞ্চিত আছে তার গড় লিখতে অপেক্ষা ~ 350 এমএস। তবে তারা প্রতি 6 মাস বা তার পরে কেবল তাদের সার্ভারটি পুনঃসূচনা করে, সুতরাং এই তথ্যটি প্রাসঙ্গিক কিনা তা আমার কোনও ধারণা নেই। টেম্পডিবি 4 টি বিভিন্ন ফাইলের উপরে ছড়িয়ে আছে তাদের ডাটাবেসের জন্য 3 টি আলাদা ফাইল রয়েছে যা সারণী সারণি ধারণ করে।

যখন একটি একক INSERT খুব দ্রুত হয় তখন কেন এই ক্যোয়ারীটি বিভিন্ন সারণিতে চালিত হয় যখন কয়েক সারি ইনসার্ট করতে লাগবে?

-- হালনাগাদ --

এখানে বাইটে পড়া সহ ড্রাইভ প্রতি বিলম্বিত নম্বর রয়েছে। আপনি দেখতে পাচ্ছেন, টেম্পডিবি পারফরম্যান্স প্রশ্নবিদ্ধ। ইনভেন্টরি সারণি PDICompany_252_01.mdf, PDICompany_252_01_Second.ndf, বা PDICompany_252_01_Third.ndf উভয় মধ্যে রয়েছে।

ReadLatencyWriteLatencyLatencyAvgBPerRead AvgBPerWriteAvgBPerTransferDriveDB                     physical_name
         42        1112    623       62171       67654          65147R:   tempdb                 R:\Microsoft SQL Server\Tempdb\tempdev1.mdf
         38        1101    615       62122       67626          65109S:   tempdb                 S:\Microsoft SQL Server\Tempdb\tempdev2.ndf
         38        1101    615       62136       67639          65123T:   tempdb                 T:\Microsoft SQL Server\Tempdb\tempdev3.ndf
         38        1101    615       62140       67629          65119U:   tempdb                 U:\Microsoft SQL Server\Tempdb\tempdev4.ndf
         25         341     71       92767       53288          87009X:   PDICompany             X:\Program Files\PDI\Enterprise\Databases\PDICompany_Third.ndf
         26         339     71       90902       52507          85345X:   PDICompany             X:\Program Files\PDI\Enterprise\Databases\PDICompany_Second.ndf
         10         231     90       98544       60191          84618W:   PDICompany_FRx         W:\Program Files\PDI\Enterprise\Databases\PDICompany_FRx.mdf
         61         137     68        9120        9181           9125W:   model                  W:\Microsoft SQL Server\MSSQL.3\MSSQL\Data\modeldev.mdf
         36         113     97        9376        5663           6419V:   model                  V:\Microsoft SQL Server\Logs\modellog.ldf
         22          99     34       92233       52112          86304W:   PDICompany             W:\Program Files\PDI\Enterprise\Databases\PDICompany.mdf
          9          20     10       25188        9120          23538W:   master                 W:\Microsoft SQL Server\MSSQL.3\MSSQL\Data\master.mdf
         20          18     19       53419       10759          40850W:   msdb                   W:\Microsoft SQL Server\MSSQL.3\MSSQL\Data\MSDBData.mdf
         23          18     19      947956       58304         110123V:   PDICompany_FRx         V:\Program Files\PDI\Enterprise\Databases\PDICompany_FRx_1.ldf
         20          17     17      828123       55295         104730V:   PDICompany             V:\Program Files\PDI\Enterprise\Databases\PDICompany.ldf
          5          13     13       12308        4868           5129V:   master                 V:\Microsoft SQL Server\Logs\mastlog.ldf
         11          13     13       22233        7598           8513V:   PDIMaster              V:\Program Files\PDI\Enterprise\Databases\PDIMaster.ldf
         14          11     13       13846        9540          12598W:   PDIMaster              W:\Program Files\PDI\Enterprise\Databases\PDIMaster.mdf
         13          11     11       22350        1107           1110V:   msdb                   V:\Microsoft SQL Server\Logs\MSDBLog.ldf
         17           9      9      745437       11821          23249V:   PDIFoundation          V:\Program Files\PDI\Enterprise\Databases\PDIFoundation.ldf
         34           8     31       29490       33725          30031W:   PDIFoundation          W:\Program Files\PDI\Enterprise\Databases\PDIFoundation.mdf
          5           8      8       61560       61236          61237V:   tempdb                 V:\Microsoft SQL Server\Logs\templog.ldf
         13           6     11        8370       35087          16785W:   SAHost_Company01       W:\Program Files\PDI\Enterprise\Databases\SAHostCompany.mdf
          2           6      5       56235       33667          38911W:   SAHost_Company01       W:\Program Files\PDI\Enterprise\Databases\SAHost_Company_01_log.LDF

মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
পল হোয়াইট 9

উত্তর:


4

দেখে মনে হচ্ছে আপনার ক্লাস্টারড ইনডেক্স পৃষ্ঠার বিভাজনগুলি বেদনাদায়ক হতে চলেছে কারণ ক্লাস্টারড ইনডেক্সটি প্রকৃত ডেটা ধারণ করে এবং এর জন্য নতুন পৃষ্ঠাগুলি বরাদ্দ করতে হবে এবং এতে ডেটা সরিয়ে নেওয়া হবে। এটির ফলে পৃষ্ঠা লক হয়ে যাওয়ার ফলে এটি ব্লক হয়ে যাওয়ার সম্ভাবনা রয়েছে।

এও মনে রাখবেন যে আপনার ক্লাস্টারড ইনডেক্স কীটি 21 বাইট এবং এটি আপনার সমস্ত গৌণ সূচকে বুকমার্ক হিসাবে সংরক্ষণ করতে হবে।

আপনি কি আপনার প্রাথমিক কী পরিচয় কলামকে আপনার ক্লাস্টারড ইনডেক্স তৈরি করার বিষয়টি বিবেচনা করেছেন, এটি কেবল আপনার অন্যান্য সূচকের আকারকেই হ্রাস করবে না, এর অর্থ এইও হবে যে আপনি আপনার ক্লাস্টারড সূচীতে পৃষ্ঠা বিভাজনের সংখ্যা হ্রাস করবেন। আপনি যদি আপনার সূচকগুলি পুনর্নির্মাণ করতে পারেন তবে এটি চেষ্টা করার মতো।


1

মাল্টি-থ্রেড পদ্ধতির সাথে, আমি কোনও টেবিলের মধ্যে সন্নিবেশ সম্পর্কে সতর্কতা অবলম্বন করছি যা থেকে আপনাকে প্রথমে কোনও কীটির পূর্বের অস্তিত্ব পরীক্ষা করতে হবে। এই ধরণের আমাকে বলে যে পিকে তালিকার সেই সারণিতে একটি চুক্তি সংক্রান্ত সমস্যা আছে যতই থ্রেডই থাকুক না কেন। একই কারণে, আমি ইনভেন্টরি টেবিলের নলক ইঙ্গিতটি পছন্দ করি না কারণ মনে হয় যে কোনও ত্রুটি ঘটবে যদি ভিন্ন থ্রেড একই কী লিখতে সক্ষম হয় (পার্টিশন প্রকল্পটি সেই সম্ভাবনাটি সরিয়ে দেয়?) আমি কৌতূহলী যে একাধিক থ্রেডের প্রাথমিক পরিচিতিতে স্পিডআপটি কতটা বড় ছিল কারণ এটি অবশ্যই কোনও পর্যায়ে ভালভাবে কাজ করেছে।

চেষ্টা করার কিছু হ'ল কোয়েরিটি আরও একটি বাল্ক অপারেশনের মতো আরও পড়তে হবে এবং "যেখানে নেই সেখানে" একটি "অ্যান্টি-জয়েন" তে রূপান্তর করা। (শেষ পর্যন্ত অপ্টিমাইজার এই প্রচেষ্টাটিকে উপেক্ষা করতে পছন্দ করতে পারে)। উপরে উল্লিখিত হিসাবে আমি গন্তব্য টেবিলে NOLOCK ইঙ্গিতটি সরিয়ে ফেলতাম যদি না সম্ভবত বিভাজনটি থ্রেডগুলির মধ্যে কোনও মূল সংঘর্ষের নিশ্চয়তা না দেয়।

 INSERT INTO i (...)
 SELECT DISTINCT ...             
   FROM tempdb..Update_Item_Work t (NOLOCK) -- nolock okay on read table
   left join Inventory i -- use without NOLOCK because PK is written inter-thread
     on i.Inv_Site_Key = t.UpdItemWrk_Site_Key
    and i.Inv_Item_Key = t.UpdItemWrk_Item_Key
    and i.Inv_Date = t.UpdItemWrk_Date
  where i.Inv_Site_Key is null   -- where not exist in inventory
    and UpdItemWrk_GUID = @GUID  -- for this thread

বেস হিসাবে চালানোর সময়টি, আপনি অন্য একটি সম্ভাবনা হিসাবে মার্জ ইঙ্গিত ("বাম যোগদান" -> "বাম সংযুক্তি যোগ করুন") দিয়ে আবার চালাতে পারেন। সংযুক্তির ইঙ্গিতটির জন্য আপনার সম্ভবত টেম্প টেবিলটিতে (আপডেটআইটেমওয়র্কসসাইট_কি, আপডেট আইটেম ওয়ার্ক_আইটেম_কি, আপডেটআইটেমওয়র্ক_ডেট) থাকা উচিত।

আমি জানি না যে এসকিউএল সার্ভার ২০০৮/২০১২ এর নতুন অ-এক্সপ্রেস সংস্করণগুলি স্বয়ংক্রিয়ভাবে এই ফর্মটির বৃহত্তর সংশ্লেষগুলিকে আপনাকে জিইউইডি-ভিত্তিক বিভাজন অপসারণের অনুমতি দিতে সক্ষম করবে।

সমস্ত আইটেমের চেয়ে স্বতন্ত্র আইটেমগুলিতে যোগদানের জন্য উত্সাহিত করার জন্য, "পৃথক নির্বাচন করুন ... ... থেকে" ধারাগুলি "এর আগে নির্বাচন করুন (আলাদা থেকে নির্বাচন করুন ... ...)" রূপান্তর করা যেতে পারে যোগ দিয়ে চালিয়ে যাচ্ছি। এটি কেবলমাত্র লক্ষণীয় পার্থক্য করতে পারে যদি স্বতন্ত্রগুলি অনেকগুলি সারি ফিল্টার করে। আবার অপ্টিমাইজার এই প্রচেষ্টাটিকে উপেক্ষা করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.