Why is mySQL query, left join 'considerably' faster than my inner join Why is mySQL query, left join 'considerably' faster than my inner join database database

Why is mySQL query, left join 'considerably' faster than my inner join


It is because of the varchar on card_id. MySQL can't use the index on card_id as card_id as described here mysql type conversion. The important part is

For comparisons of a string column with a number, MySQL cannot use an index on the column to look up the value quickly. If str_col is an indexed string column, the index cannot be used when performing the lookup in the following statement:

SELECT * FROM tbl_name WHERE str_col=1;

The reason for this is that there are many different strings that may convert to the value 1, such as '1', ' 1', or '1a'.

If you change your queries to

SELECT cl.`cl_boolean`, l.`l_name`FROM `card_legality` clINNER JOIN `legality` l ON l.`legality_id` = cl.`legality_id`WHERE cl.`card_id` = '23155'

and

SELECT cl.`cl_boolean`, l.`l_name`FROM `card_legality` clLEFT JOIN `legality` l ON l.`legality_id` = cl.`legality_id`WHERE cl.`card_id` = '23155'

You should see a huge improvement in speed and also see a different EXPLAIN.

Here is a similar (but easier) test to show this:

> desc id_test;+-------+------------+------+-----+---------+-------+| Field | Type       | Null | Key | Default | Extra |+-------+------------+------+-----+---------+-------+| id    | varchar(8) | NO   | PRI | NULL    |       |+-------+------------+------+-----+---------+-------+1 row in set (0.17 sec)> select * from id_test;+----+| id |+----+| 1  || 2  || 3  || 4  || 5  || 6  || 7  || 8  || 9  |+----+9 rows in set (0.00 sec)> explain select * from id_test where id = 1;+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+|  1 | SIMPLE      | id_test | index | PRIMARY       | PRIMARY | 10      | NULL |    9 | Using where; Using index |+----+-------------+---------+-------+---------------+---------+---------+------+------+--------------------------+1 row in set (0.00 sec)> explain select * from id_test where id = '1';+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra       |+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+|  1 | SIMPLE      | id_test | const | PRIMARY       | PRIMARY | 10      | const |    1 | Using index |+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------------+1 row in set (0.00 sec)

In the first case there is Using where; Using index and the second is Using index. Also ref is either NULL or CONST. Needless to say, the second one is better.


L2G has it pretty much summed up, although I suspect it could be because of the varchar type used for card_id.

I actually printed out this informative page for benchmarking / profiling quickies. Here is a quick poor-mans profiling technique:

Time a SQL on MySQLEnable Profilingmysql> SET PROFILING = 1...RUN your SQLs...mysql> SHOW PROFILES;+----------+------------+-----------------------+| Query_ID | Duration   | Query                 |+----------+------------+-----------------------+|        1 | 0.00014600 | SELECT DATABASE()     ||        2 | 0.00024250 | select user from user |+----------+------------+-----------------------+mysql> SHOW PROFILE for QUERY 2;+--------------------------------+----------+| Status                         | Duration |+--------------------------------+----------+| starting                       | 0.000034 || checking query cache for query | 0.000033 || checking permissions           | 0.000006 || Opening tables                 | 0.000011 || init                           | 0.000013 || optimizing                     | 0.000004 || executing                      | 0.000011 || end                            | 0.000004 || query end                      | 0.000002 || freeing items                  | 0.000026 || logging slow query             | 0.000002 || cleaning up                    | 0.000003 |+--------------------------------+----------+

Good-luck, oh and please post your findings!


I'd try EXPLAIN on both of those queries. Just prefix each SELECT with EXPLAIN and run them. It gives really useful info on how mySQL is optimizing and executing queries.