使用WHERE子句加速MySQL(MyISAM)COUNT

时间:2012-01-19 14:59:48

标签: php mysql count myisam

我们正在实施一个分析书籍的系统。该系统是用PHP编写的,每本书都循环翻译并分析每一个,从各种正则表达式和其他测试中设置某些标志(转换为数据库字段)。

这导致matches表,类似于以下示例:

+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| regex                  | varchar(250) | YES  |     | NULL    |                |
| description            | varchar(250) | NO   |     | NULL    |                |
| phonic_description     | varchar(255) | NO   |     | NULL    |                |
| is_high_frequency      | tinyint(1)   | NO   |     | NULL    |                |
| is_readable            | tinyint(1)   | NO   |     | NULL    |                |
| book_id                | bigint(20)   | YES  |     | NULL    |                |
| matched_regex          | varchar(255) | YES  |     | NULL    |                |
| [...]                  |              |      |     |         |                |
+------------------------+--------------+------+-----+---------+----------------+

大多数省略的字段是tinyint,0或1.目前匹配表中有25个字段。

匹配表中有大约2,000,000行,分析〜500本书的输出。

目前,有一个"报告"查询matches表的网站区域如下:

SELECT COUNT(*)
FROM matches
WHERE is_readable = 1
AND other_flag = 0
AND another_flag = 1

但是,目前获取主索引报告需要一分多钟,因为每个查询大约需要0.7秒。我在查询级别缓存此内容,但初始页面加载仍需要很长时间。

由于我对如何管理此类数据集不是很有经验,有人可以建议我更好地存储或查询这些数据吗?我可以使用MySQL来改善这些COUNT的性能,还是使用其他数据库或数据结构?

我们目前正在使用带有MyISAM表的MySQL和一个VPS,因此完全切换到新的数据库系统是不可能的。

2 个答案:

答案 0 :(得分:5)

您需要使用索引,并在最常使用WHERE的列上创建索引。

ALTER TABLE `matches` ADD INDEX ( `is_readable` ) 

等。

如果您使用相同类型的查询,则可以根据多个列创建索引。 phpMyAdmin在底部表格的结构页面上有索引选项。

答案 1 :(得分:4)

在您选择多个字段时,将多索引添加到此表。下面的索引应该会有很大帮助。这些类型的索引非常适合boolean / int列。对于varchar值的索引,请在此处详细阅读:http://dev.mysql.com/doc/refman/5.0/en/create-index.html

ALTER TABLE `matches` ADD INDEX ( `is_readable`, `other_flag`, `another_flag` ) 

还有一件事是使用EXPLAIN {YOUR WHOLE SQL STATEMENT}来检查查询,以检查DB使用的索引。所以在这个例子中你应该运行查询:

EXPLAIN ALTER TABLE `matches` ADD INDEX ( `is_readable`, `other_flag`, `another_flag` ) 

有关EXPLAIN的更多信息:http://dev.mysql.com/doc/refman/5.0/en/explain.html