MySQL:我应该为这些查询设置哪些索引?

时间:2013-04-15 15:38:34

标签: mysql sql

我很难确定需要编入索引的内容,以使我的查询尽可能高效。使用的表有数十亿行,所以没有索引就没用了。

我理解当我搜索带WHERE ... AND的内容时,这些列应该被编入索引,但我不明白索引如何适用于更复杂的情况,例如COUNT和{{1 }}

请有人告诉我以下查询需要哪些索引:

查询1:

ORDER BY

查询2:

SELECT word1,word2,COUNT(id) AS aaa
  FROM mytable
  WHERE (word1>0 AND word2=429907) OR (word1=429907 AND word2>0)
  GROUP BY word1,word2
  ORDER BY aaa DESC LIMIT 20;

查询3:

CREATE TEMPORARY TABLE temptbl (
  pibn INT UNSIGNED NOT NULL, page SMALLINT UNSIGNED NOT NULL)
  ENGINE=MEMORY;
INSERT INTO temptbl (
  SELECT DISTINCT pibn,page FROM mytable
  WHERE word1=429907 AND word2=0);
ALTER TABLE temptbl ADD PRIMARY KEY (pibn,page);
SELECT word1,word2,COUNT(id) AS aaa
  FROM mytable a
  INNER JOIN temptbl b
  ON a.pibn=b.pibn AND a.page=b.page
  GROUP BY word1,word2 ORDER BY aaa DESC LIMIT 10;
DROP TABLE temptbl;

目前的指数是:

SELECT pibn,COUNT(*) AS aaa
  FROM mytable
  WHERE word1=429907 AND word2=12322
  GROUP BY pibn ORDER BY aaa DESC LIMIT 25

因为它(使用当前索引)查询1需要13秒,查询2需要35秒,而查询3需要0.1秒(这听起来很快,但我认为它没有尽可能多地进行优化。)< / p>

1 个答案:

答案 0 :(得分:0)

您应该查看MySQL here中索引的使用方式。

您的第一个查询不使用索引,因为它在两列的where子句中存在不等式。为了提高效率,您需要重写查询并可能添加另一个索引。此外,如果id永远不为NULL,我认为您最好使用count(*)。这将允许查询仅使用查询扫描完成。

重写的查询看起来像:

select  word1, word2, count(*)
from ((select word1, word2
       from mytable
       where word1>0 AND word2=429907
      ) union all
      (((select word1, word2
       from mytable
       where word2>0 AND word1=429907
      )
     ) t
 group by word1, word2

出于性能原因,此查询需要mytable(word2, word1)上的索引。

如果您在子查询中首先进行聚合,然后再在外层进行聚合,则可能会更快。

您的第二个查询可能会被count(id)放慢速度。它可能正在使用group by的现有索引。然后,它需要从数据页中获取id。要么添加mytable(word1, word2, id)之类的索引,要么只需将代码更改为count(*)

第三个查询将受益于mytable(word1, word2, pibn)上的索引。