0

我有一个非常简单的 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 是否必须大于索引大小才能生效?

任何提示将不胜感激。


编辑:这是一个带有相应“解释”输出的示例:

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 的低数字查询总是比那些高数字的查询快得多。这不是我对使用索引的期望。

4

3 回答 3

2

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

  1. 改用 InnoDB 表并利用(hid1, hid2). 这样,属于同一隐藏的所有行将在物理上位于一起,这加快检索速度。

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

于 2013-05-13T12:13:06.520 回答
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找到信息

于 2013-05-13T11:41:34.633 回答
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和相关链接。

于 2013-05-13T11:24:31.790 回答