我有一个非常大的表格,用于存储电子邮件中包含的字词
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)
答案 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:如果你需要一次运行这个查询 - 只需等待它完成。如果您需要多次运行此查询 - 使用唯一字创建表并通过触发每次插入/更新/删除来更新此表中的计数