mysql查询性能帮助

时间:2010-04-22 12:54:26

标签: mysql performance group-by bigtable

我有一个非常大的表格,用于存储电子邮件中包含的字词

mysql> explain t_message_words;
+----------------+---------+------+-----+---------+----------------+
| Field          | Type    | Null | Key | Default | Extra          |
+----------------+---------+------+-----+---------+----------------+
| mwr_key        | int(11) | NO   | PRI | NULL    | auto_increment |
| mwr_message_id | int(11) | NO   | MUL | NULL    |                |
| mwr_word_id    | int(11) | NO   | MUL | NULL    |                |
| mwr_count      | int(11) | NO   |     | 0       |                |
+----------------+---------+------+-----+---------+----------------+

表包含大约100M行
mwr_message_id是消息表的FK mwr_word_id是FK到单词表
mwr_count是消息mwr_message_id中单词mwr_word_id的出现次数

要计算最常用的单词,我使用以下查询

SELECT SUM(mwr_count) AS word_count, mwr_word_id
FROM t_message_words
GROUP BY mwr_word_id
ORDER BY word_count DESC
LIMIT 100;

几乎永远运行(在测试服务器上超过半小时)

mysql> show processlist;
+----+------+----------------+--------+---------+------+----------------------+-----------------------------------------------------
| Id | User | Host           | db     | Command | Time | State                | Info
+----+------+----------------+--------+---------+------+----------------------+-----------------------------------------------------
processlist
| 41 | root | localhost:3148 | tst_db | Query   | 1955 | Copying to tmp table | SELECT SUM(mwr_count) AS word_count, mwr_word_id
    FROM t_message_words
    GROUP BY mwr_word_id |
+----+------+----------------+--------+---------+------+----------------------+-----------------------------------------------------
3 rows in set (0.00 sec)

我能做些什么来“加速”查询(除了添加更多ram,更多cpu,更快的磁盘)?

提前谢谢你 斯特凡诺

P.S。 EXPLAIN结果:

mysql> EXPLAIN SELECT SUM(mwr_count) AS word_count, mwr_word_id
    -> FROM t_message_words
    -> GROUP BY mwr_word_id
    -> ORDER BY word_count DESC
    -> LIMIT 100;
+----+-------------+-----------------+-------+---------------+----------------------+---------+------+----------+---------------------------------+
| id | select_type | table           | type  | possible_keys | key                  | key_len | ref  | rows     | Extra                           |
+----+-------------+-----------------+-------+---------------+----------------------+---------+------+----------+---------------------------------+
|  1 | SIMPLE      | t_message_words | index | NULL          | IDX_t_message_words2 | 4       | NULL | 94823285 | Using temporary; Using filesort |
+----+-------------+-----------------+-------+---------------+----------------------+---------+------+----------+---------------------------------+
1 row in set (0.01 sec)

3 个答案:

答案 0 :(得分:1)

如果你有一个mwr_message_id和mwr_word_id的索引,或者只是mwr_word_id,或者除了主键之外的任何其他索引,我都明白了。如果你没有mwr_word_id的索引(或者mwr_word_id是第一个字段),我建议你加一个。

如果你已经有了这样一个索引,这对于一个非常常见的情况来说真的很痛苦,我建议你在单词表中添加一些冗余,它总计了所有mwr_message_id中mwr_word_id的总出现次数。

您还可以向t_message_words添加一些触发器来处理此冗余的更新。

答案 1 :(得分:0)

也许mwr_word_id上的索引会有所帮助。它现在是一个键的一部分,但你可以纯粹为此添加一个键。

您还可以在配置文件中增加mysql的缓存。

答案 2 :(得分:0)

UPD:如果你需要一次运行这个查询 - 只需等待它完成。如果您需要多次运行此查询 - 使用唯一字创建表并通过触发每次插入/更新/删除来更新此表中的计数