选择 VARCHAR 字段时 JOIN 性能非常慢

JOIN performance very slow when selecting VARCHAR field

我遇到了一个查询难题,我无法找出它执行如此糟糕的原因。

请看以下查询和查询次数(使用HeidiSQL):

SELECT p.TID, a.TID
FROM characters AS p JOIN account a ON p.AccountId = a.TID;

=> rows: 57.879 Query time: 0.063 sec. (+ 0.328 sec. network)

解释:

+----+-------------+-------+-------+---------------+--------------+---------+-----------+-------+--------------------------+
| id | select_type | table | type  | possible_keys | key          | key_len | ref       | rows  | Extra                    |
+----+-------------+-------+-------+---------------+--------------+---------+-----------+-------+--------------------------+
|  1 | SIMPLE      | a     | index | TID           | WebAccountId | 5       | NULL      | 21086 | Using index              |
|  1 | SIMPLE      | p     | ref   | AccountId     | AccountId    | 5       | dol.a.TID |     1 | Using where; Using index |
+----+-------------+-------+-------+---------------+--------------+---------+-----------+-------+--------------------------+

这很快,但是一旦我 select 来自 table characters 的 VARCHAR(255) 字段,它就会变得非常慢。查看网络时间。

SELECT p.TID, a.TID, p.LastName
FROM characters AS p JOIN account a ON p.AccountId = a.TID;

=> rows: 57.879 Query time: 0.219 sec. (+ 116.234 sec. network)

+----+-------------+-------+-------+---------------+--------------+---------+-----------+-------+-------------+
| id | select_type | table | type  | possible_keys | key          | key_len | ref       | rows  | Extra       |
+----+-------------+-------+-------+---------------+--------------+---------+-----------+-------+-------------+
|  1 | SIMPLE      | a     | index | TID           | WebAccountId | 5       | NULL      | 21086 | Using index |
|  1 | SIMPLE      | p     | ref   | AccountId     | AccountId    | 5       | dol.a.TID |     1 | Using where |
+----+-------------+-------+-------+---------------+--------------+---------+-----------+-------+-------------+

查询时间仍然不错,但网络时间变得难以忍受。


有人可能认为它是由 p.LastName 的传输引起的,但看到查询 没有连接 :

SELECT p.TID, p.LastName
FROM characters AS p

=> rows: 57.881 Query time: 0.063 sec. (+ 0.578 sec. network)

+----+-------------+-------+------+---------------+------+---------+------+-------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------+
|  1 | SIMPLE      | p     | ALL  | NULL          | NULL | NULL    | NULL | 59800 |       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------+

知道这里发生了什么吗?我不知道如何解决这个问题。

编辑: 为每个查询添加了解释输出。 如果重要,它是 mysql 5.1.72-community

Edit2: 从命令行测试。同样的表现。如果我查看 mysql 进程列表,我会看到 Sending data 表示性能不佳的查询。该查询最初用于 ASP.NET web 应用程序,性能非常糟糕。这就是为什么我使用 HeidiSQL 进行调查的原因。我肯定会排除 HeidiSQL 的问题。

Edit3 Mysql Workbench 中的测试结果:

我在这里找到了罪魁祸首。我在默认设置下使用 mysql 5.1.72 和 InnoDB。

这意味着它使用了一个只有 8MB 的 InnoDB 缓冲池

innodb_buffer_pool_size=8M

Mysql 被迫将结果写入磁盘,因为一旦我将 VARCHAR 字段添加到 select 子句,它就无法将结果保存在内存中进行传输。 Join 似乎对该缓冲区的内存使用施加了更大的压力。

在我将缓冲区大小更改为 1G 之后,问题就消失了。

innodb_buffer_pool_size=1G

mysql 开始后的第一个请求仍然有点慢,但后续查询非常快。

所以这基本上是 mysql 服务器配置错误。