为什么这个MySQL查询没有正确使用索引?

为什么这个MySQL查询没有正确使用索引?,mysql,indexing,Mysql,Indexing,很抱歉,这是一个如此具体而且可能是陈词滥调的问题,但它确实给我带来了重大问题 每天我都要做数十万条类似于这两条的select语句(这是一个示例,但它们几乎相同,只是不同的word1): 第一个语句是快速的,只需几分之一秒。第二个语句大约需要2秒钟,考虑到我有成千上万的事情要做,这太长了 这些指数是: word21pibn: word2, word1, pibn word12num: word1, word2, num explain的结果(对于扩展分区和分区都是): 我看到的唯一区别是,第二条

很抱歉,这是一个如此具体而且可能是陈词滥调的问题,但它确实给我带来了重大问题

每天我都要做数十万条类似于这两条的select语句(这是一个示例,但它们几乎相同,只是不同的
word1
):

第一个语句是快速的,只需几分之一秒。第二个语句大约需要2秒钟,考虑到我有成千上万的事情要做,这太长了

这些指数是:

word21pibn: word2, word1, pibn
word12num: word1, word2, num
explain的结果(对于扩展分区和分区都是):

我看到的唯一区别是,第二条语句在descripe的额外列中没有
Using index
。虽然这没有意义,因为索引是为该语句设计的,所以我不明白为什么不使用它


有什么想法吗?

尝试将
pbin
page
列添加到
word12num
复合索引中。然后,查询所需的所有信息都将出现在索引中,就像第一次查询一样

编辑我错过了您选择的
pbin
栏;很抱歉

如果复合索引包含
(word1、word2、num、pbin、page)
,那么第二个查询中的所有内容都可以来自该索引

如果您查看第一个查询的
EXPLAIN
下的
Extra
列,其中的一个导语是
使用索引。
@sebas指出了这一点。这意味着,实际上,
只使用索引。
这意味着服务器只需查询索引即可满足您的查询,而无需查询表。这就是它如此之快的原因:服务器不必为了获得额外的列而随机访问表而对磁盘头进行重击<代码>使用索引不在第二个查询的
解释中。

中提到的列,其中
位于第一位。然后我们将列按顺序排列。最后,我们有一些列,您只需
SELECT
ing即可。为什么对索引中的列使用此特定顺序?服务器找到与
选择匹配的第一个索引项,然后可以按顺序读取索引以满足查询


在一个大表上构造和维护复合索引确实很昂贵。您正在考虑DBMS设计中的一个基本权衡:您是想花时间构建表还是在表中查找内容?只有您知道在构建表或在表中查找内容时是否最好承担成本。

您确定表中定义了此索引吗?从我所读到的,使用索引仍然要求在表上显式创建索引。是的,它是在表上定义的,正如您从explain上的
列中可以看到的。
是被选择的列,因此它不需要在索引中。@Alasdair:“需要”是有争议的;查询不需要“需要”索引中的页面来确定选择了哪一行,但它随后“需要”读取表来确定页面的值(其中页面不在索引中)。相反,如果页面是索引的一部分,那么查询根本不需要读取表——相反,它可以从索引中获取所有必需的数据。实际上,我正试图避免索引太长,因为构建它们需要很长的时间(数十亿行)我不明白第二条语句怎么会是这样,但第一条语句却不是这样。@Alasdair,在第一条语句中,所有必需的字段都包含在索引中。这就是为什么在计划的额外部分中有“使用索引”。没有扫描任何表。但是,在第二个查询中,页面列不在索引中,这就是为什么在额外部分中没有“使用索引”,因为引擎实际上必须在编译索引结果后在表中查找数据。这样做需要额外的资源。啊,是的,有道理。谢谢你给我解释。我将把这个列添加到索引中,看看它是否会重建。不过,重建索引可能需要几个小时。
word21pibn: word2, word1, pibn
word12num: word1, word2, num
mysql> explain extended SELECT pibn,COUNT(*) AS aaa FROM research_storage1 USE INDEX (word21pibn) WHERE word1=270299 AND word2=0 GROUP BY pibn ORDER BY aaa DESC LIMIT 1000;
+----+-------------+-------------------+------+---------------+------------+---------+-------------+------+----------+-----------------------------------------------------------+
| id | select_type | table             | type | possible_keys | key        | key_len | ref         | rows | filtered | Extra                                                     |
+----+-------------+-------------------+------+---------------+------------+---------+-------------+------+----------+-----------------------------------------------------------+
|  1 | SIMPLE      | research_storage1 | ref  | word21pibn    | word21pibn | 6       | const,const | 1549 |   100.00 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-------------------+------+---------------+------------+---------+-------------+------+----------+-----------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain partitions SELECT pibn,COUNT(*) AS aaa FROM research_storage1 USE INDEX (word21pibn) WHERE word1=270299 AND word2=0 GROUP BY pibn ORDER BY aaa DESC LIMIT 1000;
+----+-------------+-------------------+------------+------+---------------+------------+---------+-------------+------+-----------------------------------------------------------+
| id | select_type | table             | partitions | type | possible_keys | key        | key_len | ref         | rows | Extra                                                     |
+----+-------------+-------------------+------------+------+---------------+------------+---------+-------------+------+-----------------------------------------------------------+
|  1 | SIMPLE      | research_storage1 | p99        | ref  | word21pibn    | word21pibn | 6       | const,const | 1549 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-------------------+------------+------+---------------+------------+---------+-------------+------+-----------------------------------------------------------+
1 row in set (0.00 sec)

mysql> explain extended SELECT pibn,page FROM research_storage1 USE INDEX (word12num) WHERE word1=270299 AND word2=0 ORDER BY num DESC LIMIT 1000;
+----+-------------+-------------------+------+---------------+-----------+---------+-------------+------+----------+-------------+
| id | select_type | table             | type | possible_keys | key       | key_len | ref         | rows | filtered | Extra       |
+----+-------------+-------------------+------+---------------+-----------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | research_storage1 | ref  | word12num     | word12num | 6       | const,const |  818 |   100.00 | Using where |
+----+-------------+-------------------+------+---------------+-----------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain partitions SELECT pibn,page FROM research_storage1 USE INDEX (word12num) WHERE word1=270299 AND word2=0 ORDER BY num DESC LIMIT 1000;
+----+-------------+-------------------+------------+------+---------------+-----------+---------+-------------+------+-------------+
| id | select_type | table             | partitions | type | possible_keys | key       | key_len | ref         | rows | Extra       |
+----+-------------+-------------------+------------+------+---------------+-----------+---------+-------------+------+-------------+
|  1 | SIMPLE      | research_storage1 | p99        | ref  | word12num     | word12num | 6       | const,const |  818 | Using where |
+----+-------------+-------------------+------------+------+---------------+-----------+---------+-------------+------+-------------+
1 row in set (0.00 sec)