I am working on a social network tracking application. Even joins works fine with proper indexing. But when I add the order by clause the total query takes 100 times longer time to execute. The following query I used to get the twitter_users without order by clause.
SELECT DISTINCT `tracked_twitter`.id
FROM tracked_twitter
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id`
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id`
AND `tracker_twitter_content`.`tracker_id` = '88'
LIMIT 20
Showing rows 0 - 19 (20 total, Query took 0.0714 sec)
But when I add order by clause ( on indexed column )
SELECT DISTINCT `tracked_twitter`.id
FROM tracked_twitter
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id`
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id`
AND `tracker_twitter_content`.`tracker_id` = '88'
ORDER BY tracked_twitter.followers_count DESC
LIMIT 20
Showing rows 0 - 19 (20 total, Query took 13.4636 sec)
EXPLAIN
When I implement the order by clause in its table alone it doesn't take much time
SELECT * FROM `tracked_twitter` WHERE 1 order by `followers_count` desc limit 20
Showing rows 0 - 19 (20 total, Query took 0.0711 sec) [followers_count: 68236387 - 10525612]
The table creation query as follows
CREATE TABLE IF NOT EXISTS `tracked_twitter` (
`id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`handle` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`location` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`description` text COLLATE utf8_unicode_ci,
`profile_image` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`followers_count` int(11) NOT NULL,
`is_influencer` tinyint(1) NOT NULL DEFAULT '0',
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`gender` enum('Male','Female','Other') COLLATE utf8_unicode_ci
DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `followers_count` (`followers_count`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
So join didn't slow the query and order by working well when I execute it on its table. So how can I improve performance?
UPDATE 1
@GordonLinoff method solves if i only need the result set from parent table. What f I want to know the number tweets per person (count of twitter_content which match the tracked_twitter table). How can I modify it? And if I want to have math functions on tweet content how do I do it ??
SELECT `tracked_twitter` . * , COUNT( * ) AS twitterContentCount, retweet_count + favourite_count + reply_count AS engagement
FROM `tracked_twitter`
INNER JOIN `twitter_content` ON `tracked_twitter`.`id` = `twitter_content`.`tracked_twitter_id`
INNER JOIN `tracker_twitter_content` ON `twitter_content`.`id` = `tracker_twitter_content`.`twitter_content_id`
WHERE `is_influencer` != '1'
AND `tracker_twitter_content`.`tracker_id` = '88'
AND `tracked_twitter_id` != '0'
GROUP BY `tracked_twitter`.`id`
ORDER BY twitterContentCount DESC
LIMIT 20
OFFSET 0
This would turn this index into a covering index for this query, which should improve performance as well. Furthermore adding an index on (attribute_type_id, attribute_value, person_id) (again a covering index by including person_id) should improve performance over just using an index on attribute_value where more rows would have to be examined.
As of 8.0.20, max_length_for_sort_data is deprecated due to optimizer changes that make it obsolete and of no effect. To increase ORDER BY speed, check whether you can get MySQL to use indexes rather than an extra sorting phase. If this is not possible, try the following strategies: Increase the sort_buffer_size variable value.
“One common question that we find that, if we change the ordering of table join in case of inner join will effect or increase performance” To understand it lets take a simple example of Inner join. There is two tables named Table-A and Table-B. We can us the Inner Join on both the table. Which one is best for performance?
The query uses ORDER BY with an expression that includes terms other than the index column name: The query joins many tables, and the columns in the ORDER BY are not all from the first nonconstant table that is used to retrieve rows.
Try getting rid of the distinct
. That is a performance killer. I'm not sure why your first query works quickly; perhaps MySQL is smart enough to optimize it away.
I would try:
SELECT tt.id
FROM tracked_twitter tt
WHERE EXISTS (SELECT 1
FROM twitter_content tc INNER JOIN
tracker_twitter_content ttc
ON tc.id = ttc.twitter_content_id
WHERE ttc.tracker_id = 88 AND
tt.id = tc.tracked_twitter_id
)
ORDER BY tt.followers_count DESC ;
For this version, you want indexes on: tracked_twitter(followers_count, id)
, twitter_content(tracked_twitter_id, id)
, and
tracker_twitter_content(twitter_content_id, tracker_id)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With