লিনকিউ ফাংশনগুলির ক্রমটি কি বিবেচনা করে?


114

মূলত, প্রশ্নটি হিসাবে ... ... লিনকিউ ফাংশনগুলির ক্রম কি পারফরম্যান্সের বিবেচনায় ? স্পষ্টতই ফলাফলগুলি অভিন্ন হতে হবে ...

উদাহরণ:

myCollection.OrderBy(item => item.CreatedDate).Where(item => item.Code > 3);
myCollection.Where(item => item.Code > 3).OrderBy(item => item.CreatedDate);

দু'জনেই আমাকে একই ফলাফলগুলি ফিরিয়ে দেয় তবে ভিন্ন লিংক ক্রমে থাকে। আমি বুঝতে পারি যে কিছু আইটেমকে পুনরায় অর্ডার করার ফলে বিভিন্ন ফলাফল হবে এবং আমি সেগুলি নিয়ে উদ্বিগ্ন নই। আমার মূল উদ্বেগটি কী তা জানতে, একই ফলাফল পাওয়ার ক্ষেত্রে, অর্ডারগুলি পারফরম্যান্সকে প্রভাবিত করতে পারে knowing এবং, আমি যে দুটি লাইনকিউ কল করেছি (অর্ডার বাই, কোথায়) কেবল তা নয়, যে কোনও লিনকিউ কল রয়েছে।


9
দুর্দান্ত প্রশ্ন।
রবার্ট এস

এটি আরও সুস্পষ্ট যে আরও বেশি পেডেন্টিক কেসের সাথে সরবরাহকারীর অপ্টিমাইজেশানটি গুরুত্বপূর্ণ var query = myCollection.OrderBy(item => item.Code).Where(item => item.Code == 3);
মার্ক হার্ট

1
আপনি একটি আপ ভোট যোগ্যতা :), আকর্ষণীয় প্রশ্ন। আমি যখন আমার লিঙ্কটি ইএফ-তে সংস্থাগুলিতে লিখি তখন আমি এটি বিবেচনা করব।
গিব্বোক

1
@ গিব্বোক: আপনার লিনকিউ প্রশ্নের "অনুকূলিতকরণ" করার চেষ্টা করার সময় সতর্ক থাকুন (নীচের উত্তর দেখুন)। কখনও কখনও আপনি আসলে কিছুই অপ্টিমাইজ করা শেষ করবেন না। অপ্টিমাইজেশনের চেষ্টা করার সময় প্রোফাইলার সরঞ্জামটি ব্যবহার করা ভাল।
মায়ারামিয়ান

উত্তর:


147

এটি ব্যবহৃত লিনকিউ সরবরাহকারীর উপর নির্ভর করবে। লিনকিউ থেকে অবজেক্টের পক্ষে এটি অবশ্যই একটি বিশাল পার্থক্য করতে পারে । ধরুন আমরা আসলে পেয়েছি:

var query = myCollection.OrderBy(item => item.CreatedDate)
                        .Where(item => item.Code > 3);

var result = query.Last();

এর জন্য পুরো সংগ্রহটি বাছাই করা এবং তারপরে ফিল্টার করা দরকার। আমাদের যদি মিলিয়ন আইটেম থাকে, যার মধ্যে একটির মধ্যে 3 টিরও বেশি কোড থাকে, তবে আমরা ফলাফলগুলি অর্ডার করতে অনেক সময় নষ্ট করব যা ফেলে দেওয়া হবে।

বিপরীত অপারেশনের সাথে এর তুলনা করুন, প্রথমে ফিল্টারিং:

var query = myCollection.Where(item => item.Code > 3)
                        .OrderBy(item => item.CreatedDate);

var result = query.Last();

এবার আমরা কেবল পরিশোধিত ফলাফলের অর্ডার দিচ্ছি, যা "ফিল্টারটির সাথে মেলে কেবলমাত্র একটি আইটেম" এর নমুনার ক্ষেত্রে অনেক বেশি দক্ষ হবে - সময় এবং স্থান উভয় ক্ষেত্রেই।

এছাড়া পারে ক্যোয়ারী সঠিকভাবে বা না executes কিনা মধ্যে একটি পার্থক্য করতে। বিবেচনা:

var query = myCollection.Where(item => item.Code != 0)
                        .OrderBy(item => 10 / item.Code);

var result = query.Last();

এটি ঠিক আছে - আমরা জানি আমরা কখনই 0 দ্বারা বিভাজন করব না But তবে আমরা যদি ফিল্টারিংয়ের আগে ক্রমটি অর্ডারটি সম্পাদন করি তবে ক্যোয়ারী একটি ব্যতিক্রম ছুঁড়ে দেবে।


2
@ জোন স্কিটি, লিনকিউ সরবরাহকারী এবং ফাংশনগুলির জন্য প্রতিটি কি বিগ-ও সম্পর্কে নথিভুক্ত আছে? বা এটি কেবল "প্রতিটি অভিব্যক্তি পরিস্থিতিটির পক্ষে স্বতন্ত্র" of
মাইকেল

1
@ মাইকেল: এটি খুব স্পষ্টভাবে নথিভুক্ত নয়, তবে আপনি যদি আমার "এডুলিনক" ব্লগ সিরিজটি পড়েন তবে আমি মনে করি আমি যুক্তিসঙ্গত বিশদে এটি সম্পর্কে কথা বলব।
জন স্কিটে

3
@michael: আপনি এখানে পেতে পারেন msmvps.com/blogs/jon_skeet/archive/tags/Edulinq/default.aspx
VoodooChild

3
@ জিডোরন: সত্যি বলতে কী বোঝাতে চেয়েছেন তা সত্য নয়। আপনার মতো মনে হচ্ছে একটি নতুন প্রশ্ন লিখতে চান। মনে রাখবেন যে ক্যোয়ারিয়েবল আপনার ক্যোয়ারীটি মোটেও ব্যাখ্যা করার চেষ্টা করছে না - এর কাজটি কেবল আপনার ক্যোয়ারী সংরক্ষণ করা যাতে অন্য কিছু এটি ব্যাখ্যা করতে পারে। এছাড়াও মনে রাখবেন যে লিংক টু অবজেক্টস এমনকি অভিব্যক্তি গাছ ব্যবহার করে না।
জন স্কিটি

1
@ জিডোরন: মূল বিষয়টি হ'ল সরবরাহকারীর কাজ, ক্যোয়ারেবলের কাজ নয়। এবং সত্তা ফ্রেমওয়ার্ক ব্যবহার করার পরে এটি কোনও বিষয় নয়। এটা তোলে করেন যদিও বস্তু LINQ জন্য ব্যাপার। তবে হ্যাঁ, সব থেকে অন্য প্রশ্ন জিজ্ঞাসা করুন।
জন স্কিটি

17

হ্যাঁ.

কিন্তু ঠিক কি যে কর্মক্ষমতা পার্থক্য নেই কিভাবে অন্তর্নিহিত অভিব্যক্তি গাছ LINQ প্রদানকারীর দ্বারা মূল্যায়ন করা হয় উপর নির্ভর করে।

উদাহরণস্বরূপ, আপনার জিজ্ঞাসাটি লিনকু-টু-এক্সএমএল-এর জন্য দ্বিতীয়বার (প্রথমে WHERE ধারা সহ) দ্রুত সম্পাদন করতে পারে তবে লিনিক-টু-এসকিউএল-এর জন্য প্রথমবারের চেয়ে দ্রুত।

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


5

আপনার বিশেষ উদাহরণ এটি করতে কার্য-সম্পাদনায় একটি পার্থক্য করতে।

প্রথম ক্যোয়ারী: 3 বা তার চেয়ে কম আইটেমগুলি সহ আপনার OrderByকলটির পুরো উত্স ক্রমটি পুনরাবৃত্তি করতে হবে CodeWhereদফা তারপর এছাড়াও পুনরুক্তি করতে প্রয়োজন সমগ্র ক্রম আদেশ দেন।

দ্বিতীয়ত ক্যোয়ারী: Whereকল শুধুমাত্র ঐ আইটেম যেখানে ক্রম সীমিত Code3. চেয়ে বেশী OrderByকল তারপর শুধুমাত্র দ্বারা ফিরে কমে ক্রম তর্ক করার প্রয়োজন Whereকল।


3

লিঙ্ক-টু-অবজেক্টে:

বাছাই বরং ধীর এবং O(n)মেমরি ব্যবহার করে । Whereঅন্যদিকে তুলনামূলকভাবে দ্রুত এবং ধ্রুবক মেমরি ব্যবহার করে। সুতরাং Whereপ্রথমে করা আরও দ্রুত হবে এবং বৃহত্তর সংগ্রহের জন্য উল্লেখযোগ্যভাবে দ্রুত।

কমে যাওয়া মেমরির চাপটিও তাৎপর্যপূর্ণ হতে পারে, যেহেতু বৃহত অবজেক্টের হিপগুলিতে বরাদ্দ (তাদের সংগ্রহের সাথে একত্রে) আমার অভিজ্ঞতার তুলনায় ব্যয়বহুল।


1

স্পষ্টতই ফলাফলগুলি অভিন্ন হতে হবে ...

মনে রাখবেন যে এটি আসলে সত্য নয় - বিশেষত, নিম্নলিখিত দুটি লাইন বিভিন্ন ফলাফল দেয় (বেশিরভাগ সরবরাহকারী / ডেটাসেটের জন্য):

myCollection.OrderBy(o => o).Distinct();
myCollection.Distinct().OrderBy(o => o);

1
না, আমি যা বোঝাতে চেয়েছিলাম তা হল ফলাফলগুলি অপটিমাইজেশন বিবেচনা করার জন্যও অভিন্ন হওয়া উচিত। কোনও কিছুর "অনুকূলকরণ" এবং আলাদা ফলাফল পাওয়ার কোনও অর্থ নেই।
মাইকেল 25

1

এটি লক্ষণীয় যে আপনি কীভাবে একটি লিনকিউ ক্যোয়ারী অনুকূল করতে হবে তা বিবেচনা করার সময় সাবধান হওয়া উচিত worth উদাহরণস্বরূপ, যদি আপনি নিম্নলিখিতগুলি করতে লিনকিউ এর ঘোষণামূলক সংস্করণ ব্যবহার করেন:

public class Record
{
    public string Name { get; set; }
    public double Score1 { get; set; }
    public double Score2 { get; set; }
}


var query = from record in Records
            order by ((record.Score1 + record.Score2) / 2) descending
            select new
                   {
                       Name = record.Name,
                       Average = ((record.Score1 + record.Score2) / 2)
                   };

যদি, যে কোনও কারণেই, আপনি প্রথমে গড়কে ভেরিয়েবলের মধ্যে সঞ্চয় করে ক্যোয়ারিকে "অনুকূলিতকরণ" করার সিদ্ধান্ত নিয়েছেন, তবে আপনি পছন্দসই ফলাফল পাবেন না:

// The following two queries actually takes up more space and are slower
var query = from record in Records
            let average = ((record.Score1 + record.Score2) / 2)
            order by average descending
            select new
                   {
                       Name = record.Name,
                       Average = average
                   };

var query = from record in Records
            let average = ((record.Score1 + record.Score2) / 2)
            select new
                   {
                       Name = record.Name,
                       Average = average
                   }
            order by average descending;

আমি জানি যে অনেকেই বস্তুর জন্য ঘোষিত লিনকিউ ব্যবহার করেন না, তবে এটি চিন্তার জন্য কিছু ভাল খাবার।


0

এটি নির্ভরযোগ্যতার উপর নির্ভর করে। ধরুন আপনার কোড = 3 সহ খুব কম আইটেম রয়েছে, তবে পরবর্তী আদেশটি তারিখ অনুসারে অর্ডার পাওয়ার জন্য সংগ্রহের ছোট সেটটিতে কাজ করবে।

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

সুতরাং, উভয় ক্ষেত্রেই পারফরম্যান্সের পার্থক্য থাকবে

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