অ্যাক্টিভেকর্ড: আকার বনাম গণনা


201

রেলগুলিতে, আপনি Model.sizeএবং উভয় ব্যবহার করে রেকর্ডের সংখ্যাটি পেতে পারেন Model.count। আপনি যদি আরও জটিল প্রশ্নগুলির সাথে মোকাবিলা করছেন তবে অন্য পদ্ধতিতে একটি পদ্ধতি ব্যবহারের কোনও সুবিধা আছে কি? কিভাবে তারা ব্যতিক্রম?

উদাহরণস্বরূপ, আমার ফটোগুলি সহ ব্যবহারকারী রয়েছে। আমি যদি ব্যবহারকারীর একটি সারণী এবং তাদের কতগুলি ফটো প্রদর্শন করতে চাই, তাহলে কি অনেকগুলি উদাহরণের user.photos.sizeচেয়ে দ্রুত বা ধীর হতে পারে user.photos.count?

ধন্যবাদ!

উত্তর:


344

আপনি পড়া উচিত যে , এটা এখনও বৈধ নয়।

আপনার প্রয়োজনের উপর নির্ভর করে আপনি যে ফাংশনটি ব্যবহার করবেন তা আপনি খাপ খাইয়ে নেবেন।

মূলত:

  • যদি আপনি ইতিমধ্যে সমস্ত এন্ট্রি লোড করেন, বলুন User.all, তবে lengthঅন্য ডিবি কোয়েরি এড়াতে আপনার ব্যবহার করা উচিত

  • আপনার যদি কিছু লোড না হয়ে থাকে তবে countআপনার ডিবিতে একটি গণনা কোয়েরি করতে ব্যবহার করুন

  • আপনি যদি এই বিবেচনার সাথে বিরক্ত করতে না চান sizeতবে অভিযোজিত যা ব্যবহার করুন


35
তাহলে sizeঅবস্থা যাহাই হউক না কেন আত্তীকরণ, তাহলে কি প্রয়োজন নেই lengthএবং countএ সব?
স্কিরিরাস

27
@ এসসিআরাস - যাতে sizeআপনি যখন কল করবেন তখন এটি তাদের কাছে কল করতে পারে size(এটি নির্ধারণ করে যে কোনটি কল করবে)।
Batkins

35
যাইহোক, আকারে কেবল ডিফল্ট করার ক্ষেত্রে সাবধান হন। উদাহরণস্বরূপ, যদি আপনি সম্পর্কের মধ্য দিয়ে না গিয়ে একটি নতুন রেকর্ড তৈরি করেন, অর্থাত্ Comment.create(post_id: post.id), আপনার post.comments.sizeআপ টু ডেট হবে না, যখন post.comments.countহবে। তাই শুধু সাবধান।
mrbrdo

14
এছাড়াও, যদি আপনি কোনও সম্পর্কের মাধ্যমে বেশ কয়েকটি অবজেক্ট তৈরি করেন: এবং company.devices.build(:name => "device1"); company.devices.build(:name => "device2")তারপরে আপনি তৈরি করেছেন তবে সংরক্ষণ করেন নি এমন সংখ্যা অন্তর্ভুক্ত করবেন তবে ডাটাবেস থেকে কেবল গণনাটির প্রতিবেদন করবে। company.devices.size.length.count
শন জে গফ

6
@ এসসিআররাস, আকারটি একটি বিপজ্জনক কমান্ড যেহেতু এটি স্বয়ংক্রিয় হয়, কখনও কখনও আপনি আবার ডিবিটিকে জিজ্ঞাসা করতে চান want
অ্যালেক্স সি

79

অন্যান্য উত্তর হিসাবে বর্ণনা:

  • countএকটি এসকিউএল COUNTকোয়েরি সম্পাদন করবে
  • length ফলাফল অ্যারের দৈর্ঘ্য গণনা করবে
  • size অতিরিক্ত প্রশ্ন এড়াতে দু'জনের মধ্যে সবচেয়ে উপযুক্ত বাছাই করার চেষ্টা করবে

তবে আরও একটি বিষয় আছে। আমরা এমন একটি ক্ষেত্রে লক্ষ্য করেছি যেখানে / সম্পূর্ণরূপে sizeআলাদাভাবে কাজ করে এবং আমি ভেবেছিলাম যে এটি ভাগ করে নেওয়ার কারণ এটি বিরল।countlength

  • আপনি যদি অ্যাসোসিয়েশনে :counter_cacheকোনও ব্যবহার করেন has_many, sizeতবে ক্যাশেড গণনাটি সরাসরি ব্যবহার করবেন এবং কোনও অতিরিক্ত কোয়েরিও করবেন না।

    class Image < ActiveRecord::Base
      belongs_to :product, counter_cache: true
    end
    
    class Product < ActiveRecord::Base
      has_many :images
    end
    
    > product = Product.first  # query, load product into memory
    > product.images.size      # no query, reads the :images_count column
    > product.images.count     # query, SQL COUNT
    > product.images.length    # query, loads images into memory
    

এই আচরণটি রেল গাইডগুলিতে নথিভুক্ত করা হয়েছে তবে আমি হয় এটি প্রথমবারের মতো মিস করেছি বা এটি সম্পর্কে ভুলে গিয়েছি।


প্রকৃতপক্ষে, রেল 5.0.0.beta1 এর আগে, কোনও _countকলাম না থাকলেও ( counter_cache: trueঅ্যাসোসিয়েশনের নির্দেশ ছাড়াই ) এই আচরণটি ট্রিগার করা হবে । এটি github.com/rails/rails/commit/e0cb21f5f7
cbliard

8

কখনও কখনও size"ভুলটিকে বেছে নেয়" এবং একটি হ্যাশ ফেরত দেয় (যা তা countকরবে)

সেক্ষেত্রে হ্যাশের পরিবর্তে পূর্ণসংখ্যাlength পেতে ব্যবহার করুন ।


আমি has_many উদাহরণ থেকে সংগ্রহের জন্য '। সাইজ' ব্যবহার করেছি এবং সংগ্রহে একটি রেকর্ড থাকা সত্ত্বেও আকারটি '0' ফিরিয়ে দিচ্ছে। .Count ব্যবহার করে '1' এর সঠিক মানটি ফিরে আসে।
অ্যাডমাজোলা

4

TL; ড

  • যদি আপনি জানেন তবে আপনাকে ডেটা ব্যবহারের প্রয়োজন হবে না count
  • আপনি যদি জানেন তবে আপনি ডেটা ব্যবহার করবেন বা ব্যবহার করেছেন length
  • আপনি কী করছেন তা যদি আপনি না জানেন তবে ব্যবহার করুন size...

গণনা

Select count(*)...ডিবিতে একটি জিজ্ঞাসা প্রেরণের সমাধান করে । আপনার ডেটা প্রয়োজন না হলে যাওয়ার উপায়, তবে কেবল গণনা।

উদাহরণ: নতুন বার্তাগুলির গণনা, যখন কেবল কোনও পৃষ্ঠা প্রদর্শিত হবে তখন মোট উপাদানসমূহ etc.

লম্বা

প্রয়োজনীয় ডেটা, যেমন প্রয়োজনীয় হিসাবে ক্যোয়ারী লোড করে এবং তারপরে এটি গণনা করে। আপনি যদি ডেটা ব্যবহার করছেন তবে যাওয়ার উপায়।

উদাহরণ: সম্পূর্ণ লোড হওয়া টেবিলের সংক্ষিপ্তসার, প্রদর্শিত তথ্যের শিরোনাম ইত্যাদি

আয়তন

এটি পরীক্ষা করে যদি ডেটা লোড করা হয় (যেমন ইতিমধ্যে রেলগুলিতে থাকে) তবে কেবল এটি গণনা করুন, অন্যথায় এটি গণনা কল করে। (প্লাস সমস্যাগুলি, অন্যান্য এন্ট্রিগুলিতে ইতিমধ্যে উল্লিখিত)।

def size
  loaded? ? @records.length : count(:all)
end

সমস্যা কি?

আপনি যদি সঠিক ক্রমে এটি না করেন তবে আপনি দুবার ডিবিতে আঘাত হানতে পারেন (উদাহরণস্বরূপ, যদি আপনি রেন্ডার টেবিলের উপরে একটি সারণীতে উপাদানগুলির সংখ্যা সরবরাহ করেন, কার্যকরভাবে ডিবিতে 2 টি কল প্রেরণ করা হবে)।


3

নিম্নলিখিত কৌশলগুলি সমস্ত COUNT(*)কোয়েরি সম্পাদনের জন্য ডাটাবেসে কল করে ।

Model.count

Model.all.size

records = Model.all
records.count

নিম্নলিখিতটি এতটা দক্ষ নয় যেহেতু এটি ডাটাবেস থেকে রুবিতে সমস্ত রেকর্ড লোড করবে, যা সংগ্রহের আকারকে গণনা করে।

records = Model.all
records.size

আপনার মডেলগুলির সমিতি আছে এবং আপনি একাত্মতার বস্তুর সংখ্যা খুঁজে বের করতে চান তাহলে (যেমন @customer.orders.size), আপনি ডাটাবেস প্রশ্নের (ডিস্ক সার্চ) এড়াতে পারবেন। একটি কাউন্টার ক্যাশে ব্যবহার করুন এবং রেলগুলি ক্যাশেটির মানটি আপ টু ডেট রাখবে এবং sizeপদ্ধতির প্রতিক্রিয়াতে সেই মানটি ফিরিয়ে দেবে ।


2
উভয়ই Model.all.sizeএবং 4 টির ওপরের রেলগুলিতে Model.all.countএকটি countকোয়েরি তৈরি করে । আসল সুবিধাটি sizeহ'ল সমিতিটি ইতিমধ্যে লোড করা থাকলে এটি গণনা কোয়েরি তৈরি করে না। 3 এবং নীচে রেলগুলিতে, আমি বিশ্বাস করি Model.allযে কোনও সম্পর্ক নয়, তাই সমস্ত রেকর্ড ইতিমধ্যে লোড হয়েছে। এই উত্তরটি পুরানো হতে পারে এবং আমি এটি মোছার পরামর্শ দিই।
দামন আঃ

1

আমি আকার ফাংশন ব্যবহার করার পরামর্শ দিয়েছি।

class Customer < ActiveRecord::Base
  has_many :customer_activities
end

class CustomerActivity < ActiveRecord::Base
  belongs_to :customer, counter_cache: true
end

এই দুটি মডেল বিবেচনা করুন। গ্রাহকের অনেক গ্রাহক ক্রিয়াকলাপ রয়েছে।

যদি আপনি একটি has_many সংঘের কাউন্টার_ ক্যাশে ব্যবহার করেন, আকার সরাসরি ক্যাশেড গণনাটি ব্যবহার করবে এবং কোনও অতিরিক্ত কোয়েরি করবে না।

একটি উদাহরণ বিবেচনা করুন: আমার ডাটাবেসে একজন গ্রাহকের 20,000 গ্রাহক ক্রিয়াকলাপ রয়েছে এবং আমি সেই গ্রাহকের গ্রাহক ক্রিয়াকলাপের রেকর্ডের সংখ্যা প্রতিটি গণনা, দৈর্ঘ্য এবং আকার পদ্ধতি সহ গণনা করার চেষ্টা করি। এই সমস্ত পদ্ধতির মানদণ্ডের প্রতিবেদনের নীচে।

            user     system      total        real
Count:     0.000000   0.000000   0.000000 (  0.006105)
Size:      0.010000   0.000000   0.010000 (  0.003797)
Length:    0.030000   0.000000   0.030000 (  0.026481)

সুতরাং আমি দেখতে পেয়েছি যে: কাউন্টার_ক্যাশ আকারটি রেকর্ডের সংখ্যা গণনা করার জন্য সেরা বিকল্প।

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