对不起,这是一个特定的,可能是陈词滥调的问题,但它确实给我带来了重大问题。
每天我必须做几十万个看起来像这两个的选择语句(这是一个例子,但它们几乎只有不同的word1
):
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;
SELECT pibn,page FROM research_storage1
USE INDEX (word12num)
WHERE word1=270299 AND word2=0
ORDER BY num DESC
LIMIT 1000;
第一个声明是快速闪存,只需要几分之一秒。第二个声明需要大约2秒钟,考虑到我有数十万人要做,这太长了。
索引是:
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)
我看到的唯一区别是第二个语句在describe的额外列中没有Using index
。虽然这没有意义,因为索引是为该语句设计的,所以我不明白为什么它不会被使用。
有什么想法吗?
答案 0 :(得分:3)
尝试将pbin
和page
列添加到word12num
复合索引中。然后,您查询所需的所有信息都将在索引中,就像您在第一次查询中一样。
修改我错过了您选择的pbin
列;对于那个很抱歉。
如果您的复合索引结果包含(word1, word2, num, pbin, page)
,则第二个查询中的所有内容都可以来自索引。
如果您查看第一个查询Extra
下的EXPLAIN
列,其中一个简介Using index.
@sebas指出了这一点。实际上,这意味着Using index only.
这意味着服务器可以通过查询索引来满足您的查询,而无需查阅表。这就是为什么它如此之快:服务器不必随意访问磁盘头来获取额外的列。您的第二个查询的Using index
EXPLAIN.
WHERE
中提到的列首先出现。然后我们在ORDER BY
中有列。最后,我们只列出SELECT
个列。为什么要在索引中使用此特定顺序?服务器找到匹配SELECT
的第一个索引条目,然后可以按顺序读取索引以满足查询。
在大桌面上构建和维护复合索引确实很昂贵。您正在寻找DBMS设计的基本权衡:您是否想花时间构建表格或在其中查找内容?只有你知道在制作桌子或查看桌面时是否更好地承担费用。