Mysql +大表=慢查询?

时间:2012-05-07 15:35:40

标签: mysql

我在Mysql上有一个大表的性能问题: 该表有3800万行,大小为3GB。 我想通过测试2列进行选择: 我尝试了很多索引(每列有一个索引,有2列有一个索引)但我仍然有慢查询:如下所示,超过4秒可以获取1644行:

SELECT `twstats_twwordstrend`.`id`, `twstats_twwordstrend`.`created`, `twstats_twwordstrend`.`freq`, `twstats_twwordstrend`.`word_id` FROM `twstats_twwordstrend` WHERE (`twstats_twwordstrend`.`word_id` = 1001 AND `twstats_twwordstrend`.`created` > '2011-11-07 14:01:34' );
...
...
...
1644 rows in set (4.66 sec)

EXPLAIN SELECT `twstats_twwordstrend`.`id`, `twstats_twwordstrend`.`created`, `twstats_twwordstrend`.`freq`, `twstats_twwordstrend`.`word_id` FROM `twstats_twwordstrend` WHERE (`twstats_twwordstrend`.`word_id` = 1001 AND `twstats_twwordstrend`.`created` > '2011-11-07 14:01:34' );
+----+-------------+----------------------+-------+-----------------------------------------------------+-----------------------+---------+------+------+-------------+
| id | select_type | table                | type  | possible_keys                                       | key                   | key_len | ref  | rows | Extra       |
+----+-------------+----------------------+-------+-----------------------------------------------------+-----------------------+---------+------+------+-------------+
|  1 | SIMPLE      | twstats_twwordstrend | range | twstats_twwordstrend_4b95d890,word_id_created_index | word_id_created_index | 12      | NULL | 1643 | Using where |
+----+-------------+----------------------+-------+-----------------------------------------------------+-----------------------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> describe twstats_twwordstrend;
+---------+----------+------+-----+---------+----------------+
| Field   | Type     | Null | Key | Default | Extra          |
+---------+----------+------+-----+---------+----------------+
| id      | int(11)  | NO   | PRI | NULL    | auto_increment |
| created | datetime | NO   |     | NULL    |                |
| freq    | double   | NO   |     | NULL    |                |
| word_id | int(11)  | NO   | MUL | NULL    |                |
+---------+----------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> show index from twstats_twwordstrend;
+----------------------+------------+-------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                | Non_unique | Key_name                      | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------------------+------------+-------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| twstats_twwordstrend |          0 | PRIMARY                       |            1 | id          | A         |    38676897 |     NULL | NULL   |      | BTREE      |         |               |
| twstats_twwordstrend |          1 | twstats_twwordstrend_4b95d890 |            1 | word_id     | A         |      655540 |     NULL | NULL   |      | BTREE      |         |               |
| twstats_twwordstrend |          1 | word_id_created_index         |            1 | word_id     | A         |      257845 |     NULL | NULL   |      | BTREE      |         |               |
| twstats_twwordstrend |          1 | word_id_created_index         |            2 | created     | A         |    38676897 |     NULL | NULL   |      | BTREE      |         |               |
+----------------------+------------+-------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.03 sec)

我还发现在表格中只提取一行距离非常慢:

mysql> SELECT `twstats_twwordstrend`.`id`, `twstats_twwordstrend`.`created`, `twstats_twwordstrend`.`freq`, `twstats_twwordstrend`.`word_id` FROM `twstats_twwordstrend` limit 10000000,1;
+----------+---------------------+--------------------+---------+
| id       | created             | freq               | word_id |
+----------+---------------------+--------------------+---------+
| 10000001 | 2011-09-09 15:59:18 | 0.0013398539559188 |   41295 |
+----------+---------------------+--------------------+---------+
1 row in set (1.73 sec)

......并且在表格的开头不要慢:

mysql> SELECT `twstats_twwordstrend`.`id`, `twstats_twwordstrend`.`created`, `twstats_twwordstrend`.`freq`, `twstats_twwordstrend`.`word_id` FROM `twstats_twwordstrend` limit 1,1;
+----+---------------------+---------------------+---------+
| id | created             | freq                | word_id |
+----+---------------------+---------------------+---------+
|  2 | 2011-06-16 10:59:06 | 0.00237777777777778 |       2 |
+----+---------------------+---------------------+---------+
1 row in set (0.00 sec)

该表使用Innodb引擎。如何加快对大表的查询?

2 个答案:

答案 0 :(得分:2)

您可以做的主要是添加索引。

无论何时在where子句中使用列,请确保它具有索引。您创建的列中没有一个。

包含创建的列的多索引实质上不是创建的索引,因为创建的列不是多索引中的第一个。

使用多索引时,您应该首先将列添加到更高的基数。因此,索引为:(created, word_id)(word_id)会给你带来显着的提升。

答案 1 :(得分:1)

LIMIT 10000000,1的查询总是非常慢,因为它需要获取超过1000万行(它忽略除最后一行之外的所有行)。如果您的应用程序需要定期查询,请考虑重新设计。

表没有“开头”和“结束”;它们本身并没有订购。

在我看来,您需要一个索引(word_idcreated)。

您应该在具有生产级硬件的非生产服务器上进行性能测试。

顺便提一下,3Gb数据库现在不是太大了,除了最小的服务器之外,它将适用于所有服务器(你正在运行64位操作系统,对,并且已经适当地调整了innodb_buffer_pool?或者你的系统管理员做了什么? )。