如何使用高度冗余的键值加速数据库中的mysql选择

时间:2013-05-13 11:17:29

标签: mysql performance

我有一个非常简单的MYSQL数据库,只有3列但数百万行。 其中两个列(hid1,hid2)描述了研究对象(约50,000个),第三列(得分)是hid1与hid2比较的结果。因此,行数是max(hid1)* max(hid2),这是一个非常大的数字。因为该表只需要写一次并且读数百万次,所以我选择了一个MyISAM表(我希望这是一个好主意)。最初,我计划为一对给定的hid1,hid2检索“得分”,但结果更方便的是检索给定hid1的所有得分(和hid2)。

我的表格(“结果”)如下所示:

+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| hid1  | mediumint(8) unsigned | YES  | MUL | NULL    |       |
| hid2  | mediumint(8) unsigned | YES  |     | NULL    |       |
| score | float                 | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+

,典型的查询将是

select hid1,hid2,score from result where hid1=13531 into outfile "/tmp/ttt"

问题在于:查询花费的时间太长,至少有时候。对于某些'hid1'值,我会在一秒钟内得到结果。对于其他hid1(特别是对于大数字),我必须等待最多40秒。正如我所说,我必须运行数千个这样的查询,所以我对加快速度感兴趣。

让我重申一下:查询大约有50,000次点击,我不需要任何特定的顺序。我在这里做错了什么,或者像MySQL这样的关系数据库不能完成这项任务?

我已经尝试过在/etc/mysql/my.conf中增加key_buffer 这似乎有所帮助,但并不多。 hid1上的索引是几GB,key_buffer必须大于索引大小才有效吗?

任何暗示都会受到赞赏。


编辑:这是一个使用相应的'explain'输出运行的示例:

select hid1,hid2,score from result where hid1=132885 into outfile "/tmp/ttt"
Query OK, 16465 rows affected (31.88 sec)

如下所示,实际上正在使用索引hid1_idx:

mysql> explain select hid1,hid2,score from result where hid1=132885 into outfile "/tmp/ttt";
+----+-------------+--------+------+---------------+------------+---------+-------+-------+-------------+
| id | select_type | table  | type | possible_keys | key        | key_len | ref   | rows  | Extra       |
+----+-------------+--------+------+---------------+------------+---------+-------+-------+-------------+
|  1 | SIMPLE      | result | ref  | hid1_index    | hid1_index | 4       | const | 15456 | Using where |
+----+-------------+--------+------+---------------+------------+---------+-------+-------+-------------+

1行(0.00秒)

我觉得令人费解的是,hid1的低数字查询总是比高数字的查询要快得多。这不是我对使用索引的期望。

3 个答案:

答案 0 :(得分:2)

两个随机建议,基于始终涉及hid1上的相等过滤器的查询模式:

  1. 使用InnoDB表并利用(hid1, hid2)上的聚簇索引。这样,属于同一个隐藏的所有行都将物理地放在一起,而加速撤退。

  2. 使用合适的nr分区对hid1上的表进行哈希分区。

答案 1 :(得分:1)

优化类似查询的最简单方法是使用索引。像

这样简单的事情
alter table results add index(hid1)

会改善您发送的查询。更重要的是,如果您想同时按两个字段进行搜索,则可以在索引中使用这两个字段。

alter table results add index(hid1, hid2)

这样,MySQL可以以非常有条理的方式访问结果,并找到您想要的信息。

如果您对第一个查询运行说明,您可能会看到类似

的内容
| select_type | table  | type|possible_keys| rows   |Extra
| SIMPLE      | results| ALL |             | 7765605| Using where

添加索引后,您应该看到

| select_type | table  | type|possible_keys| rows   |Extra
| SIMPLE      | results| ref |hid1         | 2816304|

在第一种情况下,它告诉您需要检查所有行,在第二种情况下,它可以使用 ref

答案 2 :(得分:0)

如果您知道hid1和hid2的组合是唯一的,您应该考虑将其作为主键。这也会自动为hid1添加一个索引。请参阅:http://dev.mysql.com/doc/refman/5.5/en/multiple-column-indexes.html

另外,检查EXPLAIN的输出。请参阅:http://dev.mysql.com/doc/refman/5.5/en/select-optimization.html和相关链接。