সেভেন উইকেসে সেভেন ডাটাবেসগুলি থেকে দিন 3 এর প্রথম হোমওয়ার্ক প্রশ্নের উত্তর দেওয়ার জন্য আমি দুটি ফাংশন লিখেছি ।
একটি সঞ্চিত প্রক্রিয়া তৈরি করুন যেখানে আপনি কোনও সিনেমার শিরোনাম বা অভিনেতার নাম আপনার পছন্দ মতো ইনপুট করতে পারেন এবং এটি অভিনেতা অভিনীত অভিনয় করা সিনেমা বা একই ধরণের ঘরানার চলচ্চিত্রের উপর ভিত্তি করে সেরা পাঁচটি পরামর্শ ফিরিয়ে দেবে।
আমার প্রথম চেষ্টাটি সঠিক তবে ধীর। ফলাফলটি ফিরে আসতে 2000 মিমি অবধি নিতে পারে।
CREATE OR REPLACE FUNCTION suggest_movies(IN query text, IN result_limit integer DEFAULT 5)
RETURNS TABLE(movie_id integer, title text) AS
$BODY$
WITH suggestions AS (
SELECT
actors.name AS entity_term,
movies.movie_id AS suggestion_id,
movies.title AS suggestion_title,
1 AS rank
FROM actors
INNER JOIN movies_actors ON (actors.actor_id = movies_actors.actor_id)
INNER JOIN movies ON (movies.movie_id = movies_actors.movie_id)
UNION ALL
SELECT
searches.title AS entity_term,
suggestions.movie_id AS suggestion_id,
suggestions.title AS suggestion_title,
RANK() OVER (PARTITION BY searches.movie_id ORDER BY cube_distance(searches.genre, suggestions.genre)) AS rank
FROM movies AS searches
INNER JOIN movies AS suggestions ON
(searches.movie_id <> suggestions.movie_id) AND
(cube_enlarge(searches.genre, 2, 18) @> suggestions.genre)
)
SELECT suggestion_id, suggestion_title
FROM suggestions
WHERE entity_term = query
ORDER BY rank, suggestion_id
LIMIT result_limit;
$BODY$
LANGUAGE sql;
আমার দ্বিতীয় প্রচেষ্টাটি সঠিক এবং দ্রুত। আমি সিটিই থেকে ইউনিয়নের প্রতিটি অংশে ফিল্টারটি নীচে ঠেকিয়ে এটি অনুকূলিত করেছিলাম।
আমি এই লাইনটি বাইরের ক্যোয়ারী থেকে সরিয়েছি:
WHERE entity_term = query
আমি প্রথম অভ্যন্তরীণ প্রশ্নের সাথে এই লাইনটি যুক্ত করেছি:
WHERE actors.name = query
আমি এই লাইনটি দ্বিতীয় অভ্যন্তরীণ প্রশ্নের সাথে যুক্ত করেছি:
WHERE movies.title = query
দ্বিতীয় ফাংশনটি একই ফলাফলটি দেখতে 10 মিমি লাগে।
ফাংশন সংজ্ঞা ব্যতীত ডাটাবেসে কোনও কিছুই আলাদা হয় না।
পোস্টগ্র্রেএসকিউএল কেন এই দুটি যৌক্তিক সমতুল্য প্রশ্নের জন্য এই জাতীয় পরিকল্পনা তৈরি করে?
EXPLAIN ANALYZE
প্রথম ফাংশনের পরিকল্পনা ভালো দেখায়:
Limit (cost=7774.18..7774.19 rows=5 width=44) (actual time=1738.566..1738.567 rows=5 loops=1)
CTE suggestions
-> Append (cost=332.56..7337.19 rows=19350 width=285) (actual time=7.113..1577.823 rows=383024 loops=1)
-> Subquery Scan on "*SELECT* 1" (cost=332.56..996.80 rows=11168 width=33) (actual time=7.113..22.258 rows=11168 loops=1)
-> Hash Join (cost=332.56..885.12 rows=11168 width=33) (actual time=7.110..19.850 rows=11168 loops=1)
Hash Cond: (movies_actors.movie_id = movies.movie_id)
-> Hash Join (cost=143.19..514.27 rows=11168 width=18) (actual time=4.326..11.938 rows=11168 loops=1)
Hash Cond: (movies_actors.actor_id = actors.actor_id)
-> Seq Scan on movies_actors (cost=0.00..161.68 rows=11168 width=8) (actual time=0.013..1.648 rows=11168 loops=1)
-> Hash (cost=80.86..80.86 rows=4986 width=18) (actual time=4.296..4.296 rows=4986 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 252kB
-> Seq Scan on actors (cost=0.00..80.86 rows=4986 width=18) (actual time=0.009..1.681 rows=4986 loops=1)
-> Hash (cost=153.61..153.61 rows=2861 width=19) (actual time=2.768..2.768 rows=2861 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 146kB
-> Seq Scan on movies (cost=0.00..153.61 rows=2861 width=19) (actual time=0.003..1.197 rows=2861 loops=1)
-> Subquery Scan on "*SELECT* 2" (cost=6074.48..6340.40 rows=8182 width=630) (actual time=1231.324..1528.188 rows=371856 loops=1)
-> WindowAgg (cost=6074.48..6258.58 rows=8182 width=630) (actual time=1231.324..1492.106 rows=371856 loops=1)
-> Sort (cost=6074.48..6094.94 rows=8182 width=630) (actual time=1231.307..1282.550 rows=371856 loops=1)
Sort Key: searches.movie_id, (cube_distance(searches.genre, suggestions_1.genre))
Sort Method: external sort Disk: 21584kB
-> Nested Loop (cost=0.27..3246.72 rows=8182 width=630) (actual time=0.047..909.096 rows=371856 loops=1)
-> Seq Scan on movies searches (cost=0.00..153.61 rows=2861 width=315) (actual time=0.003..0.676 rows=2861 loops=1)
-> Index Scan using movies_genres_cube on movies suggestions_1 (cost=0.27..1.05 rows=3 width=315) (actual time=0.016..0.277 rows=130 loops=2861)
Index Cond: (cube_enlarge(searches.genre, 2::double precision, 18) @> genre)
Filter: (searches.movie_id <> movie_id)
Rows Removed by Filter: 1
-> Sort (cost=436.99..437.23 rows=97 width=44) (actual time=1738.565..1738.566 rows=5 loops=1)
Sort Key: suggestions.rank, suggestions.suggestion_id
Sort Method: top-N heapsort Memory: 25kB
-> CTE Scan on suggestions (cost=0.00..435.38 rows=97 width=44) (actual time=1281.905..1738.531 rows=43 loops=1)
Filter: (entity_term = 'Die Hard'::text)
Rows Removed by Filter: 382981
Total runtime: 1746.623 ms
EXPLAIN ANALYZE
দ্বিতীয় প্রশ্নের সাথে পরিকল্পনা ভালো দেখায়:
Limit (cost=43.74..43.76 rows=5 width=44) (actual time=1.231..1.234 rows=5 loops=1)
CTE suggestions
-> Append (cost=4.86..43.58 rows=5 width=391) (actual time=1.029..1.141 rows=43 loops=1)
-> Subquery Scan on "*SELECT* 1" (cost=4.86..20.18 rows=2 width=33) (actual time=0.047..0.047 rows=0 loops=1)
-> Nested Loop (cost=4.86..20.16 rows=2 width=33) (actual time=0.047..0.047 rows=0 loops=1)
-> Nested Loop (cost=4.58..19.45 rows=2 width=18) (actual time=0.045..0.045 rows=0 loops=1)
-> Index Scan using actors_name on actors (cost=0.28..8.30 rows=1 width=18) (actual time=0.045..0.045 rows=0 loops=1)
Index Cond: (name = 'Die Hard'::text)
-> Bitmap Heap Scan on movies_actors (cost=4.30..11.13 rows=2 width=8) (never executed)
Recheck Cond: (actor_id = actors.actor_id)
-> Bitmap Index Scan on movies_actors_actor_id (cost=0.00..4.30 rows=2 width=0) (never executed)
Index Cond: (actor_id = actors.actor_id)
-> Index Scan using movies_pkey on movies (cost=0.28..0.35 rows=1 width=19) (never executed)
Index Cond: (movie_id = movies_actors.movie_id)
-> Subquery Scan on "*SELECT* 2" (cost=23.31..23.40 rows=3 width=630) (actual time=0.982..1.081 rows=43 loops=1)
-> WindowAgg (cost=23.31..23.37 rows=3 width=630) (actual time=0.982..1.064 rows=43 loops=1)
-> Sort (cost=23.31..23.31 rows=3 width=630) (actual time=0.963..0.971 rows=43 loops=1)
Sort Key: searches.movie_id, (cube_distance(searches.genre, suggestions_1.genre))
Sort Method: quicksort Memory: 28kB
-> Nested Loop (cost=4.58..23.28 rows=3 width=630) (actual time=0.808..0.916 rows=43 loops=1)
-> Index Scan using movies_title on movies searches (cost=0.28..8.30 rows=1 width=315) (actual time=0.025..0.027 rows=1 loops=1)
Index Cond: (title = 'Die Hard'::text)
-> Bitmap Heap Scan on movies suggestions_1 (cost=4.30..14.95 rows=3 width=315) (actual time=0.775..0.844 rows=43 loops=1)
Recheck Cond: (cube_enlarge(searches.genre, 2::double precision, 18) @> genre)
Filter: (searches.movie_id <> movie_id)
Rows Removed by Filter: 1
-> Bitmap Index Scan on movies_genres_cube (cost=0.00..4.29 rows=3 width=0) (actual time=0.750..0.750 rows=44 loops=1)
Index Cond: (cube_enlarge(searches.genre, 2::double precision, 18) @> genre)
-> Sort (cost=0.16..0.17 rows=5 width=44) (actual time=1.230..1.231 rows=5 loops=1)
Sort Key: suggestions.rank, suggestions.suggestion_id
Sort Method: top-N heapsort Memory: 25kB
-> CTE Scan on suggestions (cost=0.00..0.10 rows=5 width=44) (actual time=1.034..1.187 rows=43 loops=1)
Total runtime: 1.410 ms