非常简单的mysql查询不使用索引

cap*_*ard 9 mysql

我的mySQL表的排序不使用索引,我不知道为什么.

我有:

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

还有这个:

EXPLAIN SELECT * 
FROM test
ORDER BY a
Run Code Online (Sandbox Code Playgroud)

以及这个

EXPLAIN SELECT * 
FROM test
USE INDEX ( kk ) 
ORDER BY a
Run Code Online (Sandbox Code Playgroud)

给我这个:

id select_type table type possible_keys key  key_len ref  rows  Extra
1  SIMPLE      test  ALL  NULL          NULL NULL    NULL 10009 Using filesort
Run Code Online (Sandbox Code Playgroud)

我不想看到这个文件,并使用密钥kk对我的表进行排序.我究竟做错了什么?


谢谢你的帖子,他们回答我的问题!但是,现在我不明白"table scan"和"filesort"的含义是什么?即使我选择了表的所有字段和所有行,通过在O(n)中遍历该列索引的内部树(然后在表中查找)来将该表排序为一列不是更快文件所请求的额外列,在O(1)中为每一行=>索引文件存储每个行在表文件中的物理位置,或?),而不是排序,例如通过快速排序在O(n*log n)中(可能)在表文件中随机存储行,而不触及索引?我想我对mySQL如何在mySQL中工作的理解是错误的.

zer*_*kms 16

  1. 您正在选择所有行
  2. 您正在选择所有列

按照我上面所说的 - mysql估计使用全扫描更有效.

要使用索引来获取它,您需要添加一些WHERE将其限制为返回的合理行数(比如50)


Bil*_*win 5

@zerkms是正确的,通过读取表中的所有行,MySQL决定无论如何都必须读取表的大部分,因此也无需读取索引。如果选择表的子集,则优化器会更改行为。

例如,我创建了一个像您一样的表,并用16384行填充它,并使用介于0和1000000之间的随机整数。然后我尝试对表的不同子集尝试EXPLAIN,首先是表的15%,然后是17%,然后是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 |
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

您也可以通过减少列数直到它只是选择索引的列来说服它使用索引。它将决定仅读取索引,而不要触摸表格。您可以根据需要定义带有额外列的索引,即使搜索或排序不需要这些列。

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 |
+----+-------------+-------+-------+---------------+------+---------+------+-------+-------------+
Run Code Online (Sandbox Code Playgroud)