Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Very simple mysql query not using index

Tags:

mysql

Sorting of my mySQL table does not use the index and I don't know why.

I've got:

CREATE TABLE IF NOT EXISTS `test` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  KEY `kk` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

and this:

EXPLAIN SELECT * 
FROM test
ORDER BY a

as well as this

EXPLAIN SELECT * 
FROM test
USE INDEX ( kk ) 
ORDER BY a

gives me this:

id select_type table type possible_keys key  key_len ref  rows  Extra
1  SIMPLE      test  ALL  NULL          NULL NULL    NULL 10009 Using filesort

I'd like not to see this filesort, and use the key kk to sort my table. What am I doing wrong?


Thank you for your posts guys, they answer my question! However, now I do not undestand what is meant by "table scan" and "filesort"? Even if I am selecting all fields and all rows of a table, isn't it faster to sort that table by one column by walking in O(n) the internal tree of the index of that column (and then looking up in the table file the extra columns requested, in O(1) for each row => the index file stores each row's physical position in the table file, or?), than to sort e.g. by quick sort in O(n * log n) the (potentially) randomly stored rows in the table file, without touching the index? I guess my understanding of how indexes work in mySQL is wrong.

like image 507
captain lizard Avatar asked Jul 17 '13 23:07

captain lizard


People also ask

Why is my query not using index?

Answer: Oracle SQL not using an index is a common complaint, and it's often because the optimizer thinks that a full-scan is cheaper than index access.

Why index is not used in MySQL?

Indexes consume disk space. Indexes degrade the performance of INSERT, UPDATE and DELETE queries – when data is updated, the index needs to be updated together with it. MySQL does not protect you from using multiple types of indexes at the same time.

Does MySQL use index for in query?

Introduction to MySQL indexesAn index is a data structure used to locate data without scanning all the rows in a table for a given query. Indexes help retrieve data faster. Indexes are not visible to the users. They help speed up queries that require a search.

How do I know if a given query uses an index or not?

Write "explain " in front of your query. The result will tell you which indexes might be used.


2 Answers

@zerkms is correct, by reading all the rows in the table, MySQL decides it's going to have to read the majority of the table anyway so there's no need to read the index as well. The optimizer changes behavior if you select a subset of the table.

For example, I created a table like yours and filled it with 16384 rows, with random integers between 0 and 1000000. Then I tried EXPLAIN for different subsets of the table, first 15% of the table, then 17%, then 19%.

mysql> EXPLAIN SELECT *  FROM test where a < 150000 ORDER BY a;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | test  | range | kk            | kk   | 5       | NULL | 2272 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+

mysql> EXPLAIN SELECT *  FROM test where a < 170000 ORDER BY a;
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | test  | range | kk            | kk   | 5       | NULL | 2560 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+

mysql> EXPLAIN SELECT *  FROM test where a < 190000 ORDER BY a;
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+
|  1 | SIMPLE      | test  | ALL  | kk            | NULL | NULL    | NULL | 16384 | Using where; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+

You can also convince it to use the index by decreasing the columns until you are just selecting the columns of the index. It'll decide to read the index alone, and not touch the table. You can define an index with extra columns if you need to, even if those columns are not needed for searching or sorting.

mysql> ALTER TABLE test ADD KEY kk2 (a,b);
mysql> EXPLAIN SELECT a,b FROM test ORDER BY a;
+----+-------------+-------+-------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | test  | index | NULL          | kk2  | 10      | NULL | 16384 | Using index |
+----+-------------+-------+-------+---------------+------+---------+------+-------+-------------+
like image 77
Bill Karwin Avatar answered Oct 12 '22 16:10

Bill Karwin


  1. You're selecting all the rows
  2. You're selecting all columns

Following what I said above - mysql estimates it to be more efficient to use full scan.

To get it using index you need to add some WHERE that would limit it to reasonable number of rows returned (say 50)

like image 43
zerkms Avatar answered Oct 12 '22 18:10

zerkms