Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, June 25, 2016

mysql left join takes too long

mysql left join takes too long


I have the following SQL Query:

SELECT       upd.*,      usr.username AS `username`,      usr.profile_picture AS `profile_picture`  FROM       updates AS upd  LEFT JOIN       subscribers AS sub ON upd.uid=sub.suid  LEFT JOIN       users AS usr ON upd.uid=usr.uid  WHERE       upd.deleted='0' && (upd.uid='118697835834' || sub.uid='118697835834')  GROUP BY upd.id  ORDER BY upd.date DESC  LIMIT 0, 15  

where i get all user(118697835834) updates, his profile picture from another table using left join and also all his subscription users updates so can i show them in his newsfeed.

However as the updates get more and more so the query takes more time to load... right now using Codeigniter's Profiler i can see that the query takes 1.3793...

Right now i have created around 18k dummy accounts and subscribed from to me and vice versa so i can test the execution time... the times that i get are tragic considering that i am in localhost...

I also have some indexes where i suppose need more in the users table(username and uid as unique), updates table(update_id as unique and uid as index)

I suppose i am doing something wrong to get so bad results...

EDIT: Running EXPLAIN EXTENDED result:

Array  (      [0] => stdClass Object          (              [id] => 1              [select_type] => SIMPLE              [table] => upd              [type] => ALL              [possible_keys] => i2              [key] =>               [key_len] =>               [ref] =>               [rows] => 22              [filtered] => 100.00              [Extra] => Using where; Using temporary; Using filesort          )        [1] => stdClass Object          (              [id] => 1              [select_type] => SIMPLE              [table] => sub              [type] => ALL              [possible_keys] =>               [key] =>               [key_len] =>               [ref] =>               [rows] => 18244              [filtered] => 100.00              [Extra] => Using where          )        [2] => stdClass Object          (              [id] => 1              [select_type] => SIMPLE              [table] => usr              [type] => eq_ref              [possible_keys] => uid              [key] => uid              [key_len] => 8              [ref] => site.upd.uid              [rows] => 1              [filtered] => 100.00              [Extra] =>           )    )  

EDIT2: SHOW CREATE of Tables Users table:

CREATE TABLE `users` (   `id` bigint(20) NOT NULL AUTO_INCREMENT,   `uid` bigint(20) NOT NULL,   `username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,   `email` text CHARACTER SET latin1 NOT NULL,   `password` text CHARACTER SET latin1 NOT NULL,   `profile_picture_full` text COLLATE utf8_unicode_ci NOT NULL,   `profile_picture` text COLLATE utf8_unicode_ci NOT NULL,   `date_registered` datetime NOT NULL,   `activated` tinyint(1) NOT NULL,   `closed` tinyint(1) NOT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `uid` (`uid`),   UNIQUE KEY `username` (`username`)  ) ENGINE=MyISAM AUTO_INCREMENT=23521 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci  

Subscribers table:

CREATE TABLE `subscribers` (   `id` bigint(20) NOT NULL AUTO_INCREMENT,   `sid` bigint(20) NOT NULL,   `uid` bigint(20) NOT NULL,   `suid` bigint(20) NOT NULL,   `date` datetime NOT NULL,   PRIMARY KEY (`id`)  ) ENGINE=MyISAM AUTO_INCREMENT=18255 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci  

Updates table:

CREATE TABLE `updates` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `update_id` bigint(19) NOT NULL,   `uid` bigint(20) NOT NULL,   `type` text COLLATE utf8_unicode_ci NOT NULL,   `update` text COLLATE utf8_unicode_ci NOT NULL,   `date` datetime NOT NULL,   `total_likes` int(11) NOT NULL,   `total_comments` int(11) NOT NULL,   `total_favorites` int(11) NOT NULL,   `category` bigint(20) NOT NULL,   `deleted` tinyint(1) NOT NULL,   `deleted_date` datetime NOT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `i1` (`update_id`),   KEY `i2` (`uid`),   KEY `deleted_index` (`deleted`)  ) ENGINE=MyISAM AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci  

Answer by Brian for mysql left join takes too long


Shouldn't take too long to run; do you have an index on 'deleted'? What is the 'GROUP BY id' doing? Should it be UID? Can it come out, if ID is in fact just an auto increment, unique ID? (which would be expensive as well as pointless)

Answer by Mark Bannister for mysql left join takes too long


Try:

SELECT       upd.*,      usr.username AS `username`,      usr.profile_picture AS `profile_picture`  FROM       updates AS upd  LEFT JOIN       subscribers AS sub ON upd.uid=sub.suid  LEFT JOIN       users AS usr ON upd.uid=usr.uid  WHERE       upd.deleted=0 and upd.uid in (118697835834,118697835834)  GROUP BY upd.id  ORDER BY upd.date DESC  LIMIT 0, 15  

Note that ' has been removed from numeric values and bitwise operators changed to conventional operators.

Answer by Luc for mysql left join takes too long


I think you'll be best separating this query into a select on the user table and then union those results with the select on the subscribers table.

Answer by user1027167 for mysql left join takes too long


don't use joins, try this one:

select  *,           (select username from users where uid = upd.uid) as username,          (select profile_picture from users where uid = upd.uid) as profile_picture,  from    updates as upd  WHERE       upd.deleted='0' && upd.uid='118697835834'  

(not tested!)

maybe you have to check if there exists a subscriber in the where-clause with another sub-select.

Another way would be to make a join on sub-selects and not on the whole table. This may increase your performance also.

Answer by ypercube?? for mysql left join takes too long


Try this one (without the GROUP BY):

SELECT       upd.*,      usr.username AS `username`,      usr.profile_picture AS `profile_picture`  FROM           updates AS upd      LEFT JOIN           users AS usr               ON  upd.uid = usr.uid  WHERE       upd.deleted='0'     AND       ( upd.uid='118697835834'     OR EXISTS        ( SELECT *          FROM   subscribers AS sub           WHERE  upd.uid = sub.suid            AND  sub.uid = '118697835834'        )      )  ORDER BY upd.date DESC  LIMIT 0, 15  

At least the columns that are used in Joins should be indexed: updates.uid, users.uid and subscribers.suid.

I would also add an index on subscribers.uid.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.