এই বাম জোট কেন লেফট জয়েন্ট লেটারেলের চেয়েও খারাপ খারাপ পারফর্ম করে?


13

আমার কাছে নিম্নলিখিত সারণী রয়েছে (সাকিলা ডাটাবেস থেকে নেওয়া):

  • ফিল্ম: ফিল্ম_আইডি পিকে
  • অভিনেতা: অভিনেতা_ পিকে আছেন
  • ফিল্ম_অ্যাক্টর: ফিল্ম_আইডি এবং অভিনেতা_আইডি ফিল্ম / অভিনেতার প্রতি অভিনেতা

আমি একটি নির্দিষ্ট চলচ্চিত্র নির্বাচন করছি। এই ফিল্মের জন্য, আমিও চাই যে সমস্ত অভিনেতা সেই ছবিতে অংশ নেবেন। এর জন্য আমার দুটি প্রশ্ন রয়েছে: একটি সাথে একটি LEFT JOINএবং একটি এর সাথে একটি LEFT JOIN LATERAL

select film.film_id, film.title, a.actors
from   film
left join
  (         
       select     film_actor.film_id, array_agg(first_name) as actors
       from       actor
       inner join film_actor using(actor_id)
       group by   film_actor.film_id
  ) as a
on       a.film_id = film.film_id
where    film.title = 'ACADEMY DINOSAUR'
order by film.title;

select film.film_id, film.title, a.actors
from   film
left join lateral
  (
       select     array_agg(first_name) as actors
       from       actor
       inner join film_actor using(actor_id)
       where      film_actor.film_id = film.film_id
  ) as a
on       true
where    film.title = 'ACADEMY DINOSAUR'
order by film.title;

ক্যোয়ারী পরিকল্পনার তুলনা করার সময়, প্রথম ক্যোয়ারী দ্বিতীয়টির চেয়ে অনেক খারাপ (20x) সম্পাদন করে:

 Merge Left Join  (cost=507.20..573.11 rows=1 width=51) (actual time=15.087..15.089 rows=1 loops=1)
   Merge Cond: (film.film_id = film_actor.film_id)
   ->  Sort  (cost=8.30..8.31 rows=1 width=19) (actual time=0.075..0.075 rows=1 loops=1)
     Sort Key: film.film_id
     Sort Method: quicksort  Memory: 25kB
     ->  Index Scan using idx_title on film  (cost=0.28..8.29 rows=1 width=19) (actual time=0.044..0.058 rows=1 loops=1)
           Index Cond: ((title)::text = 'ACADEMY DINOSAUR'::text)
   ->  GroupAggregate  (cost=498.90..552.33 rows=997 width=34) (actual time=15.004..15.004 rows=1 loops=1)
     Group Key: film_actor.film_id
     ->  Sort  (cost=498.90..512.55 rows=5462 width=8) (actual time=14.934..14.937 rows=11 loops=1)
           Sort Key: film_actor.film_id
           Sort Method: quicksort  Memory: 449kB
           ->  Hash Join  (cost=6.50..159.84 rows=5462 width=8) (actual time=0.355..8.359 rows=5462 loops=1)
             Hash Cond: (film_actor.actor_id = actor.actor_id)
             ->  Seq Scan on film_actor  (cost=0.00..84.62 rows=5462 width=4) (actual time=0.035..2.205 rows=5462 loops=1)
             ->  Hash  (cost=4.00..4.00 rows=200 width=10) (actual time=0.303..0.303 rows=200 loops=1)
               Buckets: 1024  Batches: 1  Memory Usage: 17kB
               ->  Seq Scan on actor  (cost=0.00..4.00 rows=200 width=10) (actual time=0.027..0.143 rows=200 loops=1)
 Planning time: 1.495 ms
 Execution time: 15.426 ms

 Nested Loop Left Join  (cost=25.11..33.16 rows=1 width=51) (actual time=0.849..0.854 rows=1 loops=1)
   ->  Index Scan using idx_title on film  (cost=0.28..8.29 rows=1 width=19) (actual time=0.045..0.048 rows=1 loops=1)
     Index Cond: ((title)::text = 'ACADEMY DINOSAUR'::text)
   ->  Aggregate  (cost=24.84..24.85 rows=1 width=32) (actual time=0.797..0.797 rows=1 loops=1)
     ->  Hash Join  (cost=10.82..24.82 rows=5 width=6) (actual time=0.672..0.764 rows=10 loops=1)
           Hash Cond: (film_actor.actor_id = actor.actor_id)
           ->  Bitmap Heap Scan on film_actor  (cost=4.32..18.26 rows=5 width=2) (actual time=0.072..0.150 rows=10 loops=1)
             Recheck Cond: (film_id = film.film_id)
             Heap Blocks: exact=10
             ->  Bitmap Index Scan on idx_fk_film_id  (cost=0.00..4.32 rows=5 width=0) (actual time=0.041..0.041 rows=10 loops=1)
               Index Cond: (film_id = film.film_id)
           ->  Hash  (cost=4.00..4.00 rows=200 width=10) (actual time=0.561..0.561 rows=200 loops=1)
             Buckets: 1024  Batches: 1  Memory Usage: 17kB
             ->  Seq Scan on actor  (cost=0.00..4.00 rows=200 width=10) (actual time=0.039..0.275 rows=200 loops=1)
 Planning time: 1.722 ms
 Execution time: 1.087 ms

কেন? আমি এটি সম্পর্কে যুক্তি জানাতে চাই, তাই আমি কী চলছে তা বুঝতে পারি এবং ডেটা আকার বাড়লে কোয়েরিটি কী আচরণ করবে এবং পরিকল্পনাকারী নির্দিষ্ট শর্তে কোন সিদ্ধান্ত নেবে তা অনুমান করতে পারি।

আমার চিন্তাভাবনা: প্রথম LEFT JOINক্যোয়ারিতে দেখে মনে হচ্ছে যে উপাত্তটি ডাটাবেসের সমস্ত ফিল্মের জন্য নির্বাহ করা হয়েছে, বাইরের ক্যোয়ারীতে ফিল্টারিংকে বিবেচনা না করেই আমরা কেবল একটি নির্দিষ্ট ফিল্মে আগ্রহী। পরিকল্পনাকারী কেন সাব-কোয়রিতে সেই জ্ঞান রাখতে সক্ষম নয়?

ইন LEFT JOIN LATERALক্যোয়ারী, আমরা বেশী বা কম 'ঠেলাঠেলি' যে ফিল্টারিং নীচের দিকে আছে। সুতরাং আমাদের প্রথম প্রশ্নের মধ্যে যে সমস্যাটি ছিল তা এখানে উপস্থিত নেই, সুতরাং আরও ভাল পারফরম্যান্স।

আমি অনুমান করি যে আমি মূলত থাম্বস, সাধারণ বুদ্ধি , এবং নিয়মের সন্ধান করছি ... সুতরাং এই পরিকল্পনাকারী যাদুটি দ্বিতীয় প্রকৃতিতে পরিণত হয় - যদি তা বোঝা যায়।

আপডেট (1)

LEFT JOINনিম্নলিখিত হিসাবে পুনরায় লেখাই ভাল কর্মক্ষমতা দেয় (এর চেয়ে কিছুটা ভাল LEFT JOIN LATERAL):

select film.film_id, film.title, array_agg(a.first_name) as actors
from   film
left join
  (         
       select     film_actor.film_id, actor.first_name
       from       actor
       inner join film_actor using(actor_id)
  ) as a
on       a.film_id = film.film_id
where    film.title = 'ACADEMY DINOSAUR'
group by film.film_id
order by film.title;

 GroupAggregate  (cost=29.44..29.49 rows=1 width=51) (actual time=0.470..0.471 rows=1 loops=1)
   Group Key: film.film_id
   ->  Sort  (cost=29.44..29.45 rows=5 width=25) (actual time=0.428..0.430 rows=10 loops=1)
     Sort Key: film.film_id
     Sort Method: quicksort  Memory: 25kB
     ->  Nested Loop Left Join  (cost=4.74..29.38 rows=5 width=25) (actual time=0.149..0.386 rows=10 loops=1)
           ->  Index Scan using idx_title on film  (cost=0.28..8.29 rows=1 width=19) (actual time=0.056..0.057 rows=1 loops=1)
             Index Cond: ((title)::text = 'ACADEMY DINOSAUR'::text)
           ->  Nested Loop  (cost=4.47..19.09 rows=200 width=8) (actual time=0.087..0.316 rows=10 loops=1)
             ->  Bitmap Heap Scan on film_actor  (cost=4.32..18.26 rows=5 width=4) (actual time=0.052..0.089 rows=10 loops=1)
               Recheck Cond: (film_id = film.film_id)
               Heap Blocks: exact=10
               ->  Bitmap Index Scan on idx_fk_film_id  (cost=0.00..4.32 rows=5 width=0) (actual time=0.035..0.035 rows=10 loops=1)
                 Index Cond: (film_id = film.film_id)
             ->  Index Scan using actor_pkey on actor  (cost=0.14..0.17 rows=1 width=10) (actual time=0.011..0.011 rows=1 loops=10)
               Index Cond: (actor_id = film_actor.actor_id)
 Planning time: 1.833 ms
 Execution time: 0.706 ms

আমরা কীভাবে এ বিষয়ে যুক্তি করতে পারি?

আপডেট (2)

আমি কয়েকটি পরীক্ষা-নিরীক্ষা চালিয়ে গিয়েছি এবং আমার কাছে মনে হয় থাম্বের একটি আকর্ষণীয় নিয়মটি: যতগুলি সম্ভব উচ্চ / দেরীতে সমষ্টিগত ফাংশনটি প্রয়োগ করুন । আপডেট (1) এ থাকা ক্যোয়ারী সম্ভবত আরও ভাল সম্পাদন করেছে কারণ আমরা বাহ্যিক ক্যোয়ারিতে একত্রিত করছি, অভ্যন্তরীণ কোয়েরিতে আর নেই।

আমরা যদি LEFT JOIN LATERALউপরের অংশটিকে আবার নিম্নরূপ লিখি তবে একই প্রয়োগ করা হবে বলে মনে হচ্ছে :

select film.film_id, film.title, array_agg(a.first_name) as actors
from   film
left join lateral
  (
       select     actor.first_name
       from       actor
       inner join film_actor using(actor_id)
       where      film_actor.film_id = film.film_id
  ) as a
on       true
where    film.title = 'ACADEMY DINOSAUR'
group by film.film_id
order by film.title;

 GroupAggregate  (cost=29.44..29.49 rows=1 width=51) (actual time=0.088..0.088 rows=1 loops=1)
   Group Key: film.film_id
   ->  Sort  (cost=29.44..29.45 rows=5 width=25) (actual time=0.076..0.077 rows=10 loops=1)
     Sort Key: film.film_id
     Sort Method: quicksort  Memory: 25kB
     ->  Nested Loop Left Join  (cost=4.74..29.38 rows=5 width=25) (actual time=0.031..0.066 rows=10 loops=1)
           ->  Index Scan using idx_title on film  (cost=0.28..8.29 rows=1 width=19) (actual time=0.010..0.010 rows=1 loops=1)
             Index Cond: ((title)::text = 'ACADEMY DINOSAUR'::text)
           ->  Nested Loop  (cost=4.47..19.09 rows=200 width=8) (actual time=0.019..0.052 rows=10 loops=1)
             ->  Bitmap Heap Scan on film_actor  (cost=4.32..18.26 rows=5 width=4) (actual time=0.013..0.024 rows=10 loops=1)
               Recheck Cond: (film_id = film.film_id)
               Heap Blocks: exact=10
               ->  Bitmap Index Scan on idx_fk_film_id  (cost=0.00..4.32 rows=5 width=0) (actual time=0.007..0.007 rows=10 loops=1)
                 Index Cond: (film_id = film.film_id)
             ->  Index Scan using actor_pkey on actor  (cost=0.14..0.17 rows=1 width=10) (actual time=0.002..0.002 rows=1 loops=10)
               Index Cond: (actor_id = film_actor.actor_id)
 Planning time: 0.440 ms
 Execution time: 0.136 ms

এখানে, আমরা array_agg()উপরের দিকে সরানো । আপনি দেখতে পাচ্ছেন, এই পরিকল্পনাটিও মূলটির চেয়ে ভাল LEFT JOIN LATERAL

এটি বলেছিল, আমি নিশ্চিত নই যে এই স্ব-উদ্ভাবিত নিয়মের থাম্বের নিয়মটি ( যতটা সম্ভব উচ্চ / দেরীতে সমষ্টিগত ফাংশনটি প্রয়োগ করুন ) অন্যান্য ক্ষেত্রেও সত্য।

অতিরিক্ত তথ্য

ফিডাল: https://dbfiddle.uk/?rdbms=postgres_10&fiddle=4ec4f2fffd969d9e4b949bb2ca765ffb

সংস্করণ: জিগিসি (অ্যালপাইন 6.4.0) 6.4.0, 64-বিট দ্বারা সংকলিত x86_64-pc-linux-musl এ পোস্টগ্রিএসকিউএল 10.4

পরিবেশ: Docker: docker run -e POSTGRES_PASSWORD=sakila -p 5432:5432 -d frantiseks/postgres-sakila। দয়া করে নোট করুন যে ডকার হাবের চিত্রটি পুরানো, তাই আমি প্রথমে স্থানীয়ভাবে একটি বিল্ড তৈরি করেছি: build -t frantiseks/postgres-sakilaগিট সংগ্রহস্থলটি ক্লোন করার পরে।

সারণির সংজ্ঞা:

চলচ্চিত্র

 film_id              | integer                     | not null default nextval('film_film_id_seq'::regclass)
 title                | character varying(255)      | not null

 Indexes:
    "film_pkey" PRIMARY KEY, btree (film_id)
    "idx_title" btree (title)

 Referenced by:
    TABLE "film_actor" CONSTRAINT "film_actor_film_id_fkey" FOREIGN KEY (film_id) REFERENCES film(film_id) ON UPDATE CASCADE ON DELETE RESTRICT

অভিনেতা

 actor_id    | integer                     | not null default nextval('actor_actor_id_seq'::regclass)
 first_name  | character varying(45)       | not null

 Indexes:
    "actor_pkey" PRIMARY KEY, btree (actor_id)

 Referenced by:
    TABLE "film_actor" CONSTRAINT "film_actor_actor_id_fkey" FOREIGN KEY (actor_id) REFERENCES actor(actor_id) ON UPDATE CASCADE ON DELETE RESTRICT

film_actor

 actor_id    | smallint                    | not null
 film_id     | smallint                    | not null

 Indexes:
    "film_actor_pkey" PRIMARY KEY, btree (actor_id, film_id)
    "idx_fk_film_id" btree (film_id)
 Foreign-key constraints:
    "film_actor_actor_id_fkey" FOREIGN KEY (actor_id) REFERENCES actor(actor_id) ON UPDATE CASCADE ON DELETE RESTRICT
    "film_actor_film_id_fkey" FOREIGN KEY (film_id) REFERENCES film(film_id) ON UPDATE CASCADE ON DELETE RESTRICT

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

select count(*) from film: 1000
select count(*) from actor: 200
select avg(a) from (select film_id, count(actor_id) a from film_actor group by film_id) a: 5.47

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

প্রশ্নটিতে যুক্ত হয়েছে ফিডল!
জেলি অরেন্স

উত্তর:


7

পরীক্ষা সেটআপ

উন্নতির জন্য ফিডল পাতার ঘরে আপনার আসল সেটআপ । আমি একটি কারণ জন্য আপনার সেটআপ জিজ্ঞাসা করা।

  • আপনার এই সূচকগুলি এতে রয়েছে film_actor:

    "film_actor_pkey" PRIMARY KEY, btree (actor_id, film_id)  
    "idx_fk_film_id" btree (film_id)

    যা ইতিমধ্যে বেশ সহায়ক। তবে আপনার নির্দিষ্ট ক্যোয়ারিকে সেরা সমর্থন করার জন্য, এই ক্রমে আপনার একাধিক প্রান্তের তালিকা রয়েছে on (film_id, actor_id)একটি ব্যবহারিক সমাধান: idx_fk_film_idএকটি সূচকটি প্রতিস্থাপন করুন (film_id, actor_id)- বা (film_id, actor_id)এই পরীক্ষার প্রয়োজনে পিকে তৈরি করুন , যেমন আমি নীচে করি। দেখা:

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

  • film.film_id( integer) এবং film_actor.film_id( smallint) এর মধ্যে অমিল টাইপ করুন । যদিও এটি কাজ করে এটি অনুসন্ধানগুলি ধীর করে দেয় এবং বিভিন্ন জটিলতার সৃষ্টি করতে পারে। এফকে সীমাবদ্ধতাগুলি আরও ব্যয়বহুল করে তোলে। এটি এড়ানো গেলে কখনও করবেন না do আপনি যদি নিশ্চিত না হন তবে integerউপরে উঠুন smallint। যদিও smallint পারেন ক্ষেত্র প্রতি 2 বাইট সংরক্ষণ (প্রায়ই প্রান্তিককরণ প্যাডিং খায়) সঙ্গে তুলনায় আরো জটিলতা আছে integer

  • পরীক্ষার নিজেই পারফরম্যান্স অনুকূল করতে, প্রচুর সারি বাল্ক সন্নিবেশ করার পরে সূচি এবং সীমাবদ্ধতা তৈরি করুন । উপস্থিত সমস্ত সারি দিয়ে স্ক্র্যাচ থেকে তৈরি করার চেয়ে বিদ্যমান সূচিগুলিতে ক্রমবর্ধমান টিউপল যুক্ত করা ধীরে ধীরে ধীরে ধীরে।

এই পরীক্ষার সাথে সম্পর্কিত নয়:

  • অনেক সহজ এবং আরও নির্ভরযোগ্য serial(বা IDENTITY) কলামগুলির পরিবর্তে ফ্রি-স্ট্যান্ডিং সিকোয়েন্স প্লাস কলাম ডিফল্ট । না।

  • timestamp without timestampসাধারণত একটি কলামের জন্য অবিশ্বাস্য last_updatetimestamptzপরিবর্তে ব্যবহার করুন। এবং নোট করুন যে কলাম ডিফল্টগুলি "শেষ আপডেট "টি কভার করে না , কঠোরভাবে বলছে।

  • দৈর্ঘ্যের সংশোধকটি character varying(255)ইঙ্গিত দেয় যে টেস্ট কেস পোস্টগ্র্রেস দিয়ে শুরু করার উদ্দেশ্যে নয় কারণ এখানে বিজোড় দৈর্ঘ্যটি বেশ অর্থহীন। (বা লেখক নিখরচায়।)

ভাবাবেগে নিরীক্ষিত পরীক্ষার কেসটি বিবেচনা করুন:

ডিবি <> ফিডল এখানে - আপনার ফিডল তৈরি, অনুকূলিতকরণ এবং যোগ করা প্রশ্নের সাথে।

সম্পর্কিত:

1000 টি চলচ্চিত্র এবং 200 অভিনেতাদের সাথে একটি পরীক্ষা সেটআপের বৈধতা সীমিত। সর্বাধিক দক্ষ ক্যোয়ারী <0.2 মিমি লাগে। পরিকল্পনার সময় কার্যকর করার সময়ের চেয়ে বেশি। 100k বা আরও সারি সহ একটি পরীক্ষা আরও প্রকাশ্য হবে।

কেন পুনরুদ্ধার শুধুমাত্র লেখক প্রথম নাম? একবারে আপনি একাধিক কলাম পুনরুদ্ধার করলে আপনার ইতিমধ্যে কিছুটা আলাদা পরিস্থিতি দেখা যায়।

ORDER BY titleএর সাথে একটি একক শিরোনাম ফিল্টার করার সময় কোনও অর্থবোধ করে না WHERE title = 'ACADEMY DINOSAUR'। হতে পারে ORDER BY film_id?

এবং মোট রানটাইমের জন্য বরং EXPLAIN (ANALYZE, TIMING OFF)সাব-টাইমিং ওভারহেড সহ শব্দ (সম্ভাব্য বিভ্রান্তিমূলক) কমাতে ব্যবহার করুন ।

উত্তর

থাম্বের একটি সহজ নিয়ম তৈরি করা শক্ত, কারণ মোট কর্মক্ষমতা অনেকগুলি বিষয়ের উপর নির্ভর করে। খুব প্রাথমিক নির্দেশিকা:

  • সাব-টেবিলগুলিতে সমস্ত সারি একত্রিত করা কম ওভারহেড বহন করে তবে কেবলমাত্র যখন আপনার সমস্ত সারি (বা খুব বড় অংশ) প্রয়োজন হয় তখনই অর্থ প্রদান করে।

  • কয়েকটি সারি নির্বাচনের জন্য (আপনার পরীক্ষা!), বিভিন্ন ক্যোয়ারী কৌশলগুলি আরও ভাল ফলাফল দেয়। এটি সেখানে LATERALআসে It এটি আরও ওভারহেড বহন করে তবে কেবল সাব-টেবিলগুলি থেকে প্রয়োজনীয় সারিগুলি পড়ে। একটি বড় জয় যদি কেবলমাত্র (খুব) ছোট ভগ্নাংশ প্রয়োজন হয়।

আপনার নির্দিষ্ট পরীক্ষার ক্ষেত্রে, আমি সাবকিউরিতে একটি LATERALআরআর নির্মাণকারীকেও পরীক্ষা করব :

SELECT f.film_id, f.title, a.actors
FROM   film
LEFT   JOIN LATERAL (
   SELECT ARRAY (
      SELECT a.first_name
      FROM   film_actor fa
      JOIN   actor a USING (actor_id)
      WHERE  fa.film_id = f.film_id
      ) AS actors
   ) a ON true
WHERE  f.title = 'ACADEMY DINOSAUR';
-- ORDER  BY f.title; -- redundant while we filter for a single title 

পার্শ্বীয় subquery এ শুধুমাত্র একটি একক অ্যারে একত্রিত করার সময়, একটি সাধারণ এআরএই নির্মাণকারী সমষ্টিগত ফাংশনের চেয়ে আরও ভাল সম্পাদন করে array_agg()। দেখা:

বা সাধারণ ক্ষেত্রে একটি স্বল্প সংযুক্ত subquery সঙ্গে :

SELECT f.film_id, f.title
     , ARRAY (SELECT a.first_name
              FROM   film_actor fa
              JOIN   actor a USING (actor_id)
              WHERE  fa.film_id = f.film_id) AS actors
FROM   film f
WHERE  f.title = 'ACADEMY DINOSAUR';

বা, খুব মূলত, মাত্র 2x LEFT JOINএবং তারপরে সমষ্টি :

SELECT f.film_id, f.title, array_agg(a.first_name) AS actors
FROM   film f
LEFT   JOIN film_actor fa USING (film_id)
LEFT   JOIN actor a USING (actor_id)
WHERE  f.title = 'ACADEMY DINOSAUR'
GROUP  BY f.film_id;

এই তিনটি আমার আপডেট হওয়া ফিডলটিতে (পরিকল্পনা + কার্যকর করার সময়) সবচেয়ে দ্রুত বলে মনে হচ্ছে।

আপনার প্রথম প্রচেষ্টা (কেবলমাত্র কিছুটা সংশোধিত) সাধারণত সমস্ত বা সর্বাধিক চলচ্চিত্র পুনরুদ্ধার করার জন্য দ্রুততম হয় তবে ছোট নির্বাচনের জন্য নয়:

SELECT f.film_id, f.title, a.actors
FROM   film f
LEFT   JOIN (         
   SELECT fa.film_id, array_agg(first_name) AS actors
   FROM   actor
   JOIN   film_actor fa USING (actor_id)
   GROUP  by fa.film_id
   ) a USING (film_id)
WHERE  f.title = 'ACADEMY DINOSAUR';  -- not good for a single (or few) films!

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

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