আমার একটি ক্যোয়ারী রয়েছে যা চালাতে বিশেষত দীর্ঘ সময় নিচ্ছে (15+ সেকেন্ড) এবং আমার ডেটাসেট বাড়ার সাথে সাথে এটি কেবল সময়ের সাথে আরও খারাপ হচ্ছে। আমি অতীতে এটি অনুকূলিত করেছি, এবং সূচকগুলি, কোড-স্তরের বাছাই এবং অন্যান্য অপ্টিমাইজেশানগুলি যুক্ত করেছি, তবে এটি আরও কিছু পুনরায় পরিমার্জন প্রয়োজন।
SELECT sounds.*, avg(ratings.rating) AS avg_rating, count(ratings.rating) AS votes FROM `sounds`
INNER JOIN ratings ON sounds.id = ratings.rateable_id
WHERE (ratings.rateable_type = 'Sound'
AND sounds.blacklisted = false
AND sounds.ready_for_deployment = true
AND sounds.deployed = true
AND sounds.type = "Sound"
AND sounds.created_at > "2011-03-26 21:25:49")
GROUP BY ratings.rateable_id
ক্যোয়ারির উদ্দেশ্য হল আমার sound id
সর্বাধিক সাম্প্রতিক, প্রকাশিত শব্দের গড় রেটিং। প্রায় 1500 শব্দ এবং 2 মিলিয়ন রেটিং রয়েছে।
আমার বেশ কয়েকটি সূচক রয়েছে sounds
mysql> show index from sounds;
+--------+------------+------------------------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+————+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+------------------------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+————+
| sounds | 0 | PRIMARY | 1 | id | A | 1388 | NULL | NULL | | BTREE | |
| sounds | 1 | sounds_ready_for_deployment_and_deployed | 1 | deployed | A | 5 | NULL | NULL | YES | BTREE | |
| sounds | 1 | sounds_ready_for_deployment_and_deployed | 2 | ready_for_deployment | A | 12 | NULL | NULL | YES | BTREE | |
| sounds | 1 | sounds_name | 1 | name | A | 1388 | NULL | NULL | | BTREE | |
| sounds | 1 | sounds_description | 1 | description | A | 1388 | 128 | NULL | YES | BTREE | |
+--------+------------+------------------------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+
এবং বেশ কয়েকটি ratings
mysql> show index from ratings;
+---------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+————+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+————+
| ratings | 0 | PRIMARY | 1 | id | A | 2008251 | NULL | NULL | | BTREE | |
| ratings | 1 | index_ratings_on_rateable_id_and_rating | 1 | rateable_id | A | 18 | NULL | NULL | | BTREE | |
| ratings | 1 | index_ratings_on_rateable_id_and_rating | 2 | rating | A | 9297 | NULL | NULL | YES | BTREE | |
+---------+------------+-----------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
এখানে EXPLAIN
mysql> EXPLAIN SELECT sounds.*, avg(ratings.rating) AS avg_rating, count(ratings.rating) AS votes FROM sounds INNER JOIN ratings ON sounds.id = ratings.rateable_id WHERE (ratings.rateable_type = 'Sound' AND sounds.blacklisted = false AND sounds.ready_for_deployment = true AND sounds.deployed = true AND sounds.type = "Sound" AND sounds.created_at > "2011-03-26 21:25:49") GROUP BY ratings.rateable_id;
+----+-------------+---------+--------+--------------------------------------------------+-----------------------------------------+---------+-----------------------------------------+---------+——————+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+--------+--------------------------------------------------+-----------------------------------------+---------+-----------------------------------------+---------+——————+
| 1 | SIMPLE | ratings | index | index_ratings_on_rateable_id_and_rating | index_ratings_on_rateable_id_and_rating | 9 | NULL | 2008306 | Using where |
| 1 | SIMPLE | sounds | eq_ref | PRIMARY,sounds_ready_for_deployment_and_deployed | PRIMARY | 4 | redacted_production.ratings.rateable_id | 1 | Using where |
+----+-------------+---------+--------+--------------------------------------------------+-----------------------------------------+---------+-----------------------------------------+---------+-------------+
আমি একবারে প্রাপ্ত ফলাফলগুলিতে ক্যাশে করি, তাই সাইটের কার্য সম্পাদন কোনও সমস্যার বেশি হয় না, তবে আমার ক্যাশে ওয়ার্মাররা এই কলটি এত বেশি সময় নিয়ে যাওয়ার কারণে চালাতে আরও বেশি সময় নিচ্ছে এবং এটি একটি ইস্যুতে পরিণত হতে শুরু করেছে। এটি একটি ক্যোয়ারিতে ক্রাঙ্ক করার মতো অনেক সংখ্যার মতো বলে মনে হচ্ছে না ...
এটিকে আরও ভালভাবে সম্পাদন করতে আমি আরও কী করতে পারি ?
EXPLAIN
আউটপুট দেখাতে পারবেন ?EXPLAIN SELECT sounds.*, avg(ratings.rating) AS avg_rating, count(ratings.rating) AS votes FROM sounds INNER JOIN ratings ON sounds.id = ratings.rateable_id WHERE (ratings.rateable_type = 'Sound' AND sounds.blacklisted = false AND sounds.ready_for_deployment = true AND sounds.deployed = true AND sounds.type = "Sound" AND sounds.created_at > "2011-03-26 21:25:49") GROUP BY ratings.rateable_id