রেলগুলি: বনাম অন্তর্ভুক্ত: যোগ দেয়


345

এটি "আমি কীভাবে এটি করতে হয় তা জানি না" "প্রশ্নটির চেয়ে এটি" কেন বিষয়গুলি এভাবে কাজ করে "প্রশ্নটি আরও ...

সুতরাং সম্পর্কিত রেকর্ডগুলি যে আপনি জানেন যে আপনি ব্যবহার করতে যাচ্ছেন তা টানতে দেওয়া সুসমাচারটি হ'ল ব্যবহার করা :includeকারণ আপনি একটি যোগদান পেয়ে যাবেন এবং অতিরিক্ত অনুসন্ধানের পুরো গুচ্ছটি এড়িয়ে যাবেন:

Post.all(:include => :comments)

তবে আপনি যখন লগগুলিতে লক্ষ্য করেন, সেখানে কোনও যোগসূত্র হয় না:

Post Load (3.7ms)   SELECT * FROM "posts"
Comment Load (0.2ms)   SELECT "comments.*" FROM "comments" 
                       WHERE ("comments".post_id IN (1,2,3,4)) 
                       ORDER BY created_at asc) 

এটা তোলে হয় একটি শর্টকাট গ্রহণ করা হয়েছে কারণ এটি একবারে মন্তব্য সব pulls, কিন্তু এটি এখনও একটি যোগদানের নয় (যা কি সব ডকুমেন্টেশন বলে মনে হয়)। আমি যোগদানের একমাত্র উপায় হ'ল :joinsপরিবর্তে ব্যবহার করা :include:

Post.all(:joins => :comments)

এবং লগগুলি দেখায়:

Post Load (6.0ms)  SELECT "posts".* FROM "posts" 
                   INNER JOIN "comments" ON "posts".id = "comments".post_id

আমি কিছু অনুপস্থিত করছি? আমার অর্ধ ডজন সমিতি সহ একটি অ্যাপ্লিকেশন রয়েছে এবং এক স্ক্রিনে আমি এগুলির সমস্ত থেকে ডেটা প্রদর্শন করি। দেখে মনে হচ্ছে 6 জন ব্যক্তির পরিবর্তে একটি যুক্ত-এড কোয়েরি রাখা ভাল be আমি জানি যে পারফরম্যান্স-ভিত্তিতে পৃথক প্রশ্নের পরিবর্তে যোগদান করা ভাল নয় (আসলে আপনি যদি সময় ব্যয় করে যাচ্ছেন তবে দেখে মনে হচ্ছে উপরোক্ত দুটি পৃথক প্রশ্নগুলি যোগ দেওয়ার চেয়ে দ্রুত) তবে সমস্ত দস্তাবেজের পরে আমি পড়ছি আমি :includeবিজ্ঞাপন হিসাবে কাজ না করে দেখে অবাক ।

হয়তো পাগল হয় কার্য-সম্পাদনার সমস্যা জ্ঞাত এবং নির্দিষ্ট ক্ষেত্রে ব্যতীত যোগদানের না?


3
যদি আপনি রেলগুলির একটি পুরানো সংস্করণ ব্যবহার করে থাকেন তবে দয়া করে তা ট্যাগের মাধ্যমে বা আপনার প্রশ্নবঙ্গিতে লিখুন। অন্যথায়, আপনি যদি এখনই 4 টি includes
রেলগুলি

এছাড়াও এখন রয়েছে: প্রিললোড এবং: উত্সাহী_লোড ব্লগ.বাইগাইনারি
07

উত্তর:


179

দেখা যাচ্ছে যে :includeকার্যকারিতাটি রেল ২.১ দিয়ে পরিবর্তন করা হয়েছিল। রেলগুলি সমস্ত ক্ষেত্রে যোগদান করতে ব্যবহৃত হত, তবে কার্য সম্পাদনের কারণে কিছু পরিস্থিতিতে একাধিক প্রশ্ন ব্যবহার করার জন্য এটি পরিবর্তন করা হয়েছিল। ফ্যাবিও আকিতার এই ব্লগ পোস্টটিতে পরিবর্তনের বিষয়ে কিছু ভাল তথ্য রয়েছে ("অপটিমাইজড ইজার লোডিং" শিরোনামে বিভাগটি দেখুন)।



ধন্যবাদ এটি খুব সহায়ক। যদিও আমার ইচ্ছা ছিল যে কোনও উপায় নেই যেখানে এমনকি "যেখানে" ছাড়াই রেলদের যোগ দিতে বাধ্য করার একটি উপায় ছিল। কিছু ক্ষেত্রে, আপনি জানেন যে যোগদানটি আরও দক্ষ হবে এবং সদৃশ হওয়ার ঝুঁকি বহন করবে না।
জোনাথন সোয়ার্টজ


@ জোনাথানসওয়ার্টজ মনে হচ্ছে নতুন সংস্করণ রেলগুলি উত্সাহী চাপ ব্যবহার করে এটি সমর্থন করে । লিঙ্কটি নাথানলংয়ের জন্য ধন্যবাদ
রুবপ্রিন্স

92

.joinsকেবল সারণিতে যোগদান করে এবং পরিবর্তে নির্বাচিত ক্ষেত্র নিয়ে আসবে। যদি আপনি কোয়েরি ফলাফলের সাথে সংযুক্তিগুলি কল করেন, এটি আবার ডাটাবেস প্রশ্নের উত্সাহিত করবে

:includesঅন্তর্ভুক্ত সমিতিগুলি উত্সাহিত করবে এবং তাদের স্মৃতিতে যুক্ত করবে। :includesসমস্ত অন্তর্ভুক্ত সারণী বৈশিষ্ট্য লোড করে। যদি আপনি জিজ্ঞাসার ফলাফল অন্তর্ভুক্ত করার বিষয়ে অ্যাসোসিয়েশনগুলিতে কল করেন তবে এটি কোনও প্রশ্নের উদ্রেক করবে না


71

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

উদাহরণস্বরূপ, যদি আপনার মন্তব্যে পূর্ণ একটি টেবিল থাকে এবং আপনি বাছাইকরণের উদ্দেশ্যে সমস্ত ব্যবহারকারীর তথ্য টেনে আনার জন্য যুক্ত হন>> ব্যবহারকারীগণ ব্যবহার করেন, ইত্যাদি এটি ভাল কাজ করবে এবং এর চেয়ে কম সময় নিবে: অন্তর্ভুক্ত করুন, তবে বলুন যে আপনি প্রদর্শন করতে চান ব্যবহারকারীর নাম, ইমেল ইত্যাদির সাথে মতামত ব্যবহার করে তথ্যগুলি যোগ করতে: যোগ দেয়, এটি প্রাপ্ত প্রতিটি ব্যবহারকারীর জন্য পৃথক এসকিউএল অনুসন্ধান করতে হবে, আপনি যদি ব্যবহার করেন তবে অন্তর্ভুক্ত করুন এই তথ্যটি ব্যবহারের জন্য প্রস্তুত।

দুর্দান্ত উদাহরণ:

http://railscasts.com/episodes/181-include-vs-joins


55

আমি সম্প্রতি :joinsএবং এর মধ্যে পার্থক্য সম্পর্কে আরও পড়ছিলাম:includes রেলের । আমি যা বুঝেছিলাম তার একটি ব্যাখ্যা এখানে (উদাহরণ সহ :))

এই পরিস্থিতিতে বিবেচনা করুন:

  • একজন ব্যবহারকারীর_সংখ্যক মন্তব্য এবং একটি মন্তব্য একজন ব্যবহারকারীর_র সাথে রয়েছে।

  • ব্যবহারকারীর মডেলটিতে নিম্নলিখিত বৈশিষ্ট্য রয়েছে: নাম (স্ট্রিং), বয়স (পূর্ণসংখ্যা)। মন্তব্য মডেলটিতে নিম্নলিখিত বৈশিষ্ট্য রয়েছে: সামগ্রী, ব্যবহারকারী_আইডি। একটি মন্তব্যের জন্য একটি ব্যবহারকারী_দল নਾਲ হতে পারে।

যোগদান করেছে:

: দুটি টেবিলের মধ্যে একটি অভ্যন্তরীণ যোগদান সম্পাদনা করে। এইভাবে

Comment.joins(:user)

#=> <ActiveRecord::Relation [#<Comment id: 1, content: "Hi I am Aaditi.This is my first   comment!", user_id: 1, created_at: "2014-11-12 18:29:24", updated_at: "2014-11-12 18:29:24">, 
     #<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,    
     #<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">]>

আনা হবে যেখানে USER_ID (মন্তব্য টেবিলের) সকল রেকর্ড user.id (ব্যবহারকারীদের টেবিল) সমান। আপনি যদি এইভাবে

Comment.joins(:user).where("comments.user_id is null")

#=> <ActiveRecord::Relation []>

প্রদর্শিত হিসাবে আপনি একটি খালি অ্যারে পাবেন।

তবুও যোগ দেয় মেমরিতে যুক্ত টেবিলটি লোড করে না। আপনি যদি এইভাবে

comment_1 = Comment.joins(:user).first

comment_1.user.age
#=>←[1m←[36mUser Load (0.0ms)←[0m  ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1←[0m  [["id", 1]]
#=> 24

আপনি যেমন দেখেন, comment_1.user.ageফলাফল পেতে পটভূমিতে আবার একটি ডাটাবেস ক্যোয়ারী ফায়ার করবে

সহ:

: অন্তর্ভুক্ত দুটি টেবিলের মধ্যে একটি বাম বাইরের জোড় সঞ্চালন । এইভাবে

Comment.includes(:user)

#=><ActiveRecord::Relation [#<Comment id: 1, content: "Hi I am Aaditi.This is my first comment!", user_id: 1, created_at: "2014-11-12 18:29:24", updated_at: "2014-11-12 18:29:24">,
   #<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,
   #<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">,    
   #<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>

মন্তব্য সারণী থেকে সমস্ত রেকর্ড সহ একটি যোগদান টেবিল ফলাফল হবে আপনি যদি এইভাবে

Comment.includes(:user).where("comment.user_id is null")
#=> #<ActiveRecord::Relation [#<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>

এটি রেকর্ডগুলি আনবে যেখানে মতামত.ইউজার_আইডি শূন্য রয়েছে shown

তবুও মেমরির উভয় টেবিল লোড অন্তর্ভুক্ত। আপনি যদি এইভাবে

comment_1 = Comment.includes(:user).first

comment_1.user.age
#=> 24

আপনি মন্তব্য_1 লক্ষ্য করতে পারেন যে পটভূমিতে একটি ডাটাবেস ক্যোয়ারী গুলি না করেই কেবল মেমরি থেকে ফলাফল লোড করে u


এটা কি 4 রেলের জন্য?
ওয়ানব্রি

@ হান্টারস্টেভেনস: হ্যাঁ এটি
অদিতি জৈন

54

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


10

TL; ড

আমি তাদের দুটি উপায়ে বিপরীত করছি:

যোগদান - রেকর্ড শর্তাধীন নির্বাচনের জন্য।

অন্তর্ভুক্ত - ফলাফল সেট প্রতিটি সদস্যের একটি সমিতি ব্যবহার করার সময়।

দীর্ঘ সংস্করণ

যোগদানের অর্থ ডাটাবেস থেকে আসা ফলাফল সেটটি ফিল্টার করা। আপনি আপনার টেবিলে সেট অপারেশন করতে এটি ব্যবহার করেন। সেটাকে তত্ত্ব সম্পাদন করে এমন একটি ধারা হিসাবে এটি ভাবুন।

Post.joins(:comments)

হিসাবে একই

Post.where('id in (select post_id from comments)')

একাধিক মন্তব্য থাকলে আপনি ডুপ্লিকেট পোস্টে যোগদানের সাথে ফিরে পাবেন। তবে প্রতিটি পোস্টই এমন একটি পোস্ট হবে যাতে মন্তব্য থাকবে। আপনি এটিকে স্বতন্ত্রভাবে সংশোধন করতে পারেন:

Post.joins(:comments).count
=> 10
Post.joins(:comments).distinct.count
=> 2

চুক্তি অনুসারে, includesপদ্ধতিটি সহজভাবে নিশ্চিত করে তুলবে যে সম্পর্কের উল্লেখ করার সময় কোনও অতিরিক্ত ডাটাবেস প্রশ্ন নেই (যাতে আমরা এন + 1 অনুসন্ধান না করি)

Post.includes(:comments).count
=> 4 # includes posts without comments so the count might be higher.

নৈতিক হ'ল, joinsআপনি যখন শর্তসাপেক্ষ সেট অপারেশন করতে চান includesতখন ব্যবহার করুন এবং আপনি যখন কোনও সংগ্রহের প্রতিটি সদস্যের সাথে সম্পর্ক ব্যবহার করতে যাচ্ছেন তখন ব্যবহার করুন।


যা distinctআমাকে প্রতিবার পেয়ে যায়। ধন্যবাদ!
বেন হাল

4

.joins ডাটাবেস জয়েন হিসাবে কাজ করে এবং এটি দুই বা ততোধিক টেবিলের সাথে যোগ দেয় এবং ব্যাকএন্ড (ডাটাবেস) থেকে নির্বাচিত ডেটা সংগ্রহ করে।

.Dame ডাটাবেসের বাম জোড় হিসাবে কাজ অন্তর্ভুক্ত। এটি বাম পাশের সমস্ত রেকর্ড লোড করেছে, ডান হাতের মডেলের প্রাসঙ্গিকতা নেই। এটি আগ্রহী লোডিংয়ের জন্য ব্যবহৃত হয় কারণ এটি মেমরিতে সমস্ত সম্পর্কিত বস্তুকে লোড করে। যদি আমরা অ্যাসোসিয়েশনগুলিকে কোয়েরি ফলাফল অন্তর্ভুক্ত করে কল করি তবে এটি ডেটাবেজে কোনও জিজ্ঞাসা চালায় না, এটি কেবল মেমরি থেকে ডেটা ফেরত দেয় কারণ এটি ইতিমধ্যে মেমরিতে ডেটা লোড করেছে।


0

'যোগ দেয়' সবেমাত্র টেবিলগুলিতে যোগ দিতে ব্যবহৃত হয়েছিল এবং আপনি যখন অ্যাসোসিয়েশনগুলিতে যোগ দিয়েছিলেন তখন এটি আবার জিজ্ঞাসা ফায়ার করবে (এর অর্থ অনেক জিজ্ঞাসা ফায়ার হবে)

lets suppose you have tow model, User and Organisation
User has_many organisations
suppose you have 10 organisation for a user 
@records= User.joins(:organisations).where("organisations.user_id = 1")
QUERY will be 
 select * from users INNER JOIN organisations ON organisations.user_id = users.id where organisations.user_id = 1

it will return all records of organisation related to user
and @records.map{|u|u.organisation.name}
it run QUERY like 
select * from organisations where organisations.id = x then time(hwo many organisation you have)

এক্ষেত্রে এসকিউএল এর মোট সংখ্যা ১১ টি

তবে 'অন্তর্ভুক্ত' এর সাহায্যে অন্তর্ভুক্ত সংস্থাগুলি উত্সাহিত করবে এবং তাদের মেমোরিতে যুক্ত করবে (সমস্ত ভারতে প্রথম অ্যাসোসিয়েশন লোড করবে) এবং পুনরায় ফায়ার ক্যোয়ারী নয়

আপনি যখন রেকর্ডগুলি পান @ রেকর্ডস = ব্যবহারকারীর সাথে অন্তর্ভুক্ত (: সংস্থা)। কোথাও ("অঙ্গসংগঠন.ইউজার_আইডি = 1") এর সাথে রেকর্ড পাবেন তখন কোয়েরি হবে

select * from users INNER JOIN organisations ON organisations.user_id = users.id where organisations.user_id = 1
and 


 select * from organisations where organisations.id IN(IDS of organisation(1, to 10)) if 10 organisation
and when you run this 

@ রেকর্ড.ম্যাপ {| u | u.organisation.name} কোনও জিজ্ঞাসা চালানো হবে না

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