জ্যাঙ্গোতে, আমার দেওয়া হয়েছে যে আমি QuerySet
পুনরাবৃত্তি করতে যাচ্ছি এবং ফলাফলগুলি মুদ্রণ করতে যাচ্ছি, অবজেক্টগুলি গণনা করার জন্য সেরা বিকল্পটি কী? len(qs)
বা qs.count()
?
(এছাড়াও একই পুনরাবৃত্তিতে অবজেক্টগুলি গণনা করা কোনও বিকল্প নয় given)
জ্যাঙ্গোতে, আমার দেওয়া হয়েছে যে আমি QuerySet
পুনরাবৃত্তি করতে যাচ্ছি এবং ফলাফলগুলি মুদ্রণ করতে যাচ্ছি, অবজেক্টগুলি গণনা করার জন্য সেরা বিকল্পটি কী? len(qs)
বা qs.count()
?
(এছাড়াও একই পুনরাবৃত্তিতে অবজেক্টগুলি গণনা করা কোনও বিকল্প নয় given)
উত্তর:
যদিও জ্যাঙ্গো ডক্সcount
পরিবর্তে ব্যবহার করার পরামর্শ দেয় len
:
দ্রষ্টব্য:
len()
আপনি যা করতে চান তা যদি সেটে রেকর্ডের সংখ্যা নির্ধারণ করে তবে কোয়েরিসেটে ব্যবহার করবেন না । এটি এসকিউএল এর সাহায্যে ডাটাবেস স্তরে একটি গণনা পরিচালনা করতে অনেক বেশি দক্ষSELECT COUNT(*)
এবং জ্যাঙ্গোcount()
ঠিক এই কারণে একটি পদ্ধতি সরবরাহ করে ।
আপনি এই QuerySet যাহাই হউক না কেন iterating যেহেতু, ফলাফলের ক্যাশে করা হবে (যদি না আপনি ব্যবহার করছেন iterator
), এবং তাই এটি ব্যবহার করা বাঞ্ছনীয় হতে হবে len
, যেহেতু এই এড়াতে ফলাফল একটি আলাদা নম্বর পুনরুদ্ধারের এর সম্ভবত আবার ডাটাবেসের আঘাত, এবং এছাড়াও !) ।
আপনি যদি ব্যবহার করে থাকেন iterator
তবে আমি একই কারণে আপনি কাউন্টের পরিবর্তনের (গণনা ব্যবহার না করে) পুনরাবৃত্তি করার সাথে সাথে একটি গণনা ভেরিয়েবল অন্তর্ভুক্ত করার পরামর্শ দেব।
এর মধ্যে বাছাই করা len()
এবং count()
পরিস্থিতির উপর নির্ভর করে এবং তারা কীভাবে এগুলি সঠিকভাবে ব্যবহার করতে কাজ করে তা গভীরভাবে বুঝতে পারা উচিত।
আমাকে আপনাকে কয়েকটি পরিস্থিতি সরবরাহ করতে দিন:
(অত্যন্ত গুরুত্বপূর্ণ) যখন আপনি কেবলমাত্র উপাদানের সংখ্যা জানতে চান এবং আপনি যে কোনও উপায়ে এটি ব্যবহার করা গুরুত্বপূর্ণ হিসাবে তাদের প্রক্রিয়া করার পরিকল্পনা করেন না count()
:
করুন: queryset.count()
- এটি একক SELECT COUNT(*) some_table
ক্যোয়ারী করবে, সমস্ত গণনা আরডিবিএমএসের দিকে চালিত হবে, পাইথনকে কেবল ও (1) এর নির্ধারিত ব্যয়ের সাথে ফলাফলের সংখ্যাটি উদ্ধার করতে হবে
করবেন না: len(queryset)
- এটি SELECT * FROM some_table
কোয়েরি সম্পাদন করবে , পুরো টেবিল ও (এন) এনেছে এবং এটি সংরক্ষণের জন্য অতিরিক্ত ও (এন) মেমরির প্রয়োজন হবে। এটি করা যেতে পারে সবচেয়ে খারাপ
আপনি যেভাবে যাইহোক ক্যোয়ারেটটি আনার ইচ্ছাকৃত তা ব্যবহার করা কিছুটা ভাল len()
যা কোনও অতিরিক্ত ডাটাবেস ক্যোয়ারির কারণ হবে না count()
:
len(queryset) # fetching all the data - NO extra cost - data would be fetched anyway in the for loop
for obj in queryset: # data is already fetched by len() - using cache
pass
গণনা:
queryset.count() # this will perform an extra db query - len() did not
for obj in queryset: # fetching data
pass
প্রত্যাবর্তিত ২ য় কেস (যখন ক্যোয়ারসেট ইতিমধ্যে আনা হয়েছে):
for obj in queryset: # iteration fetches the data
len(queryset) # using already cached data - O(1) no extra cost
queryset.count() # using cache - O(1) no extra db query
len(queryset) # the same O(1)
queryset.count() # the same: no query, O(1)
আপনি একবার "হুডের নীচে" এক নজরে নিলে সবকিছু পরিষ্কার হয়ে যাবে:
class QuerySet(object):
def __init__(self, model=None, query=None, using=None, hints=None):
# (...)
self._result_cache = None
def __len__(self):
self._fetch_all()
return len(self._result_cache)
def _fetch_all(self):
if self._result_cache is None:
self._result_cache = list(self.iterator())
if self._prefetch_related_lookups and not self._prefetch_done:
self._prefetch_related_objects()
def count(self):
if self._result_cache is not None:
return len(self._result_cache)
return self.query.get_count(using=self.db)
জাজানো ডক্সে ভাল রেফারেন্স:
QuerySet
প্রাসঙ্গিকভাবে বাস্তবায়ন পোস্ট করার জন্য +1 ।
আমি মনে করি len(qs)
যে ফলাফলগুলি আপনাকে পুনরাবৃত্তি করতে হবে তাই এখানে ব্যবহার আরও বোধগম্য। qs.count()
আপনি যা করতে চান তার সবগুলিই কাউন্টটি মুদ্রণ করুন এবং ফলাফলগুলির উপরে পুনরাবৃত্তি না করা যদি এটি একটি ভাল বিকল্প।
len(qs)
ডাটাবেস হিট করবে select * from table
যেখানে qs.count()
ডিবি দিয়ে আঘাত করবে select count(*) from table
।
এছাড়াও qs.count()
প্রত্যাবর্তন পূর্ণসংখ্যা দেবে এবং আপনি এটির উপরে পুনরাবৃত্তি করতে পারবেন না
পরীক্ষার পরিমাপ পছন্দ করে এমন লোকদের জন্য (পোস্টারস্কেল):
যদি আমাদের কাছে একটি সহজ ব্যক্তি মডেল এবং এর 1000 টি উদাহরণ রয়েছে:
class Person(models.Model):
name = models.CharField(max_length=100)
age = models.SmallIntegerField()
def __str__(self):
return self.name
গড় ক্ষেত্রে এটি দেয়:
In [1]: persons = Person.objects.all()
In [2]: %timeit len(persons)
325 ns ± 3.09 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [3]: %timeit persons.count()
170 ns ± 0.572 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
সুতরাং আপনি কীভাবে এই বিশেষ পরীক্ষার ক্ষেত্রে count()
প্রায় 2x দ্রুত দেখতে পাচ্ছেন len()
।
অন্যরা ইতিমধ্যে কী জবাব দিয়েছে তা সংক্ষেপে:
len()
সমস্ত রেকর্ড আনবে এবং সেগুলি পুনরাবৃত্তি করবে।count()
একটি এসকিউএল COUNT অপারেশন সম্পাদন করবে (বড় ক্যোয়ারসেটের সাথে ডিল করার সময় অনেক দ্রুত)।এটিও সত্য যে যদি এই অপারেশনের পরে, পুরো ক্যোয়ারসেটটি পুনরাবৃত্তি করা হবে, তবে সামগ্রিকভাবে এটি ব্যবহারে কিছুটা দক্ষ হতে পারে len()
।
যাহোক
কিছু ক্ষেত্রে, উদাহরণস্বরূপ যখন মেমরির সীমাবদ্ধতা থাকে, তখন রেকর্ডগুলির উপর সঞ্চালিত ক্রিয়াকলাপটি বিভক্ত করা সুবিধাজনক (যখন সম্ভব হয়) হতে পারে। এটি জাঙ্গো পৃষ্ঠাগুলি ব্যবহার করে অর্জন করা যেতে পারে ।
তারপরে, ব্যবহার count()
করা পছন্দ হবে এবং আপনি একবারে পুরো ক্যোরিসেটটি আনতে পারবেন না।