我很难确定需要编入索引的内容,以使我的查询尽可能高效。使用的表有数十亿行,所以没有索引就没用了。
我理解当我搜索带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>
答案 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)
上的索引。