Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mysql IN clause full table scan

Tags:

sql

mysql

I have a test table (table1) with 6 records in it. I wanted to fetch data based on column (col1) for multiple values. So i indexed the column. Now if i pass multiple values in IN clause selecting all columns(*) with forced index, i get particular records instead of full table scan. If i run same query with selected column i see that it does full table scan.

I have read that using select all (*) in select query is not good. But here if i don't use select all (*) there will be a full table scan. I'm not able to understand how mysql reads the query. Please help me to sort out this issue.

TABLE

+----+--------+---------+
| id | col1   | col2    |
+----+--------+---------+
|  1 | 100000 | E100000 |
|  2 | 100001 | E200001 |
|  3 | 100002 | E300002 |
|  4 | 100003 | E400003 |
|  5 | 100004 | E500004 |
|  6 | 100005 | E600005 |
+----+--------+---------+

INDEX

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| table1   |          0 | PRIMARY  |            1 | id          | A         |           6 |     NULL | NULL   |      | BTREE      |         |               |
| table1   |          1 | col1     |            1 | col1        | A         |           6 |     NULL | NULL   |      | BTREE      |         |               |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

EXPLAIN (USING FORCE INDEX (col1) AND selecting all(*) columns)

select * from table1 force index(col1) where col1 in ('100000', '100001');

+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table    | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | table1   | range | col1          | col1  | 10      | NULL |    2 | Using where |
+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+

EXPLAIN (USING FORCE INDEX (col1) AND selecting only 1 column data instead of all(*))

select col1 from table1 force index(col1) where col1 in ('100000', '100001');

+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table    | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | table1   | range | col1          | col1  | 10      | NULL |    6 | Using where; Using index |
+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+
like image 385
sravis Avatar asked Oct 03 '22 19:10

sravis


1 Answers

  1. MySQL optimizer sees that the table is too small and full scan will be more efficient than searching an index first and retrieving data later.
  2. When you select only one column, MySQL optimizer sees, that this column is in the index, and it is not necessary to retrieve data from the table - reading the index is enough.

How optimizer determine what is more efficient? It tries to predict quantity of disk read-block operations.

As it was mentioned before in comments, on big table EXPLAIN would be different.

like image 198
Alexey Ruzin Avatar answered Oct 07 '22 20:10

Alexey Ruzin