1
SELECT COALESCE(tb2.numero_novo, tb1.numero_original) as numero
FROM
tb1
LEFT JOIN tb2 ON tb2.id = tb1.id
WHERE
tb1.numero_original = <PARAM> OR tb2.numero_novo = <PARAM>
The above query generates a full table scan. How to optimize this query?
EXPLAIN:
+----+-------------+-------+-------+----------------+----------------+---------+------+----------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+----------------+----------------+---------+------+----------+----------------------------------------------------+
| 1 | SIMPLE | tb1 | index | numero_original| numero_original| 5 | NULL | 11683843 | Using index |
| 1 | SIMPLE | tb2 | ALL | PRIMARY | NULL | NULL | NULL | 2 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+----------------+----------------+---------+------+----------+----------------------------------------------------+
The problem I need to solve is:
tb1
is a table containing the field numero_original
. I want to create the table tb2
to store a new value for this field, (which I called numero_novo
). I did it because I can’t change the field value numero_original
, and would not want to create the field numero_novo
on the table tb1
, because it would be NULL in over 95% of the 11 million record table.
EDIT:
As they talked about indexes, I’m putting more information:
tb1
has as primary key the fieldid
;- The field
numero_original
tabletb1
has an index; tb2
has as primary key the fieldstb1_id
andnumero_novo
;- The table
tb1
has 11mi+ records; - The newly created table
tb2
has 2 test records.
.
mysql> show indexes from tb1;
+-------+------------+-------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb1 | 0 | PRIMARY | 1 | id | A | 11066164 | NULL | NULL | | BTREE | | |
| tb1 | 1 | numero_original | 1 | numero_original | A | 5533082 | NULL | NULL | YES | BTREE | | |
+-------+------------+-------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
mysql> show indexes from tb2;
+-------+------------+------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb2 | 0 | PRIMARY | 1 | tb1_id | A | 2 | NULL | NULL | | BTREE | | |
| tb2 | 0 | PRIMARY | 2 | numero_novo | A | 2 | NULL | NULL | | BTREE | | |
+-------+------------+------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
EXPLAIN by selecting with WHERE only in the first table (tb1
):
+----+-------------+-------+------+----------------+----------------+---------+-------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+----------------+----------------+---------+-------+------+----------------------------------------------------+
| 1 | SIMPLE | tb1 | ref | numero_original| numero_original| 5 | const | 4 | Using index |
| 1 | SIMPLE | tb2 | ALL | PRIMARY | NULL | NULL | NULL | 2 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+----------------+----------------+---------+-------+------+----------------------------------------------------+
EXPLAIN by selecting with WHERE only in the second table (tb2
):
+----+-------------+-------+--------+---------------+---------+---------+-------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-------------------------+------+-------------+
| 1 | SIMPLE | tb2 | ALL | PRIMARY | NULL | NULL | NULL | 2 | Using where |
| 1 | SIMPLE | tb1 | eq_ref | PRIMARY | PRIMARY | 4 | sistema.tb2.tb1_id | 1 | NULL |
+----+-------------+-------+--------+---------------+---------+---------+-------------------------+------+-------------+
Is it Mysql? SQL Server? Don’t forget to [Edit] the tags of your question.
– gmsantos
Mysql. Already updated, thanks.
– Raul Baldner Junior
All you care about are the lines of
tb2
where there is ID correspondence with thetb1
? In that case you could use oneINNER JOIN
instead of theLEFT
.– bfavaretto
I need the lines of
tb1
, even if there are no lines in thetb2
– Raul Baldner Junior
@Raulbaldnerjunior as only explain
SELECT COALESCE(tb2.numero_novo, tb1.numero_original) as numero
FROM
tb1
LEFT JOIN tb2 ON tb2.id = tb1.id
WHERE 
tb1.numero_original = <PARAM>
– gmsantos
@gmsantos edited the question to add this information
– Raul Baldner Junior