首页 > 解决方案 > (内部)加入此表时导致此内存泄漏的原因是什么?

问题描述

我脑子里有 SQL,它会并且应该在 1 秒内运行:

SELECT mem.`epid`,
       mem.`model_id`,
       em.`UKM_Make`,
       em.`UKM_Model`,
       em.`UKM_CCM`,
       em.`UKM_Submodel`,
       em.`Year`,
       em.`UKM_StreetName`,
       f.`fit_part_number`
FROM `table_one` AS mem
INNER JOIN `table_two` em ON mem.`epid` = em.`ePID`
INNER JOIN `table_three` f ON `mem`.`model_id` = f.`fit_model_id`
LIMIT 1;

当我在终端中运行时,此 SQL 将在 16 秒内执行。但是,如果我删除该行:

INNER JOIN `table_three` f ON `mem`.`model_id` = f.`fit_model_id`

然后它在 0.03 秒内执行。对我来说不幸的是,我不确定如何调试 MYSQL 性能问题。这会导致我的 PHP 脚本在尝试执行查询时耗尽内存。

这是我的表结构:

table_one

+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| epid     | int(11) | YES  |     | NULL    |       |
| model_id | int(11) | YES  |     | NULL    |       |
+----------+---------+------+-----+---------+-------+

表二

+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id             | int(11)      | NO   | PRI | NULL    |       |
| ePID           | int(11)      | NO   |     | NULL    |       |
| UKM_Make       | varchar(100) | NO   |     | NULL    |       |
| UKM_Model      | varchar(100) | NO   |     | NULL    |       |
| UKM_CCM        | int(11)      | NO   |     | NULL    |       |
| UKM_Submodel   | varchar(100) | NO   |     | NULL    |       |
| Year           | int(11)      | NO   |     | NULL    |       |
| UKM_StreetName | varchar(100) | NO   |     | NULL    |       |
| Vehicle Type   | varchar(100) | NO   |     | NULL    |       |
+----------------+--------------+------+-----+---------+-------+

表三

+-----------------+-------------+------+-----+---------+----------------+
| Field           | Type        | Null | Key | Default | Extra          |
+-----------------+-------------+------+-----+---------+----------------+
| fit_fitment_id  | int(11)     | NO   | PRI | NULL    | auto_increment |
| fit_part_number | varchar(50) | NO   |     | NULL    |                |
| fit_model_id    | int(11)     | YES  |     | NULL    |                |
| fit_year_start  | varchar(4)  | YES  |     | NULL    |                |
| fit_year_end    | varchar(4)  | YES  |     | NULL    |                |
+-----------------+-------------+------+-----+---------+----------------+

以上是从describe $table_name

有什么我明显遗漏的东西吗?如果没有,我该如何尝试找出为什么包含table_three会导致响应时间如此缓慢?

编辑一:

在索引建议之后(使用CREATE INDEX fit_model ON table_three (fit_model_id),它在 0.00 秒内执行查询(在 MYSQL 中)。删除限制,在执行建议后仍在运行......所以不完全存在。安东关于使用 EXPLAIN 的建议我使用它并得到了这个输出:

+------+-------------+-------+------+---------------+-----------+---------+----------------------+-------+-------------------------------------------------+
| id   | select_type | table | type | possible_keys | key       | key_len | ref                  | rows  | Extra                                           |
+------+-------------+-------+------+---------------+-----------+---------+----------------------+-------+-------------------------------------------------+
|    1 | SIMPLE      | mem   | ALL  | NULL          | NULL      | NULL    | NULL                 |  5587 | Using where                                     |
|    1 | SIMPLE      | f     | ref  | fit_model     | fit_model | 5       | mastern.mem.model_id |    14 |                                                 |
|    1 | SIMPLE      | em    | ALL  | NULL          | NULL      | NULL    | NULL                 | 36773 | Using where; Using join buffer (flat, BNL join) |
+------+-------------+-------+------+---------------+-----------+---------+----------------------+-------+-------------------------------------------------+

编辑两个

我使用以下查询根据建议添加了外键:

ALTER TABLE `table_one`
ADD CONSTRAINT `model_id_fk_tbl_three`
FOREIGN KEY (`model_id`)
REFERENCES `table_three` (`fit_model_id`)

MYSQL 仍在执行命令 - 有很多行,所以一半期待这种行为。使用 PHP,我可以分解查询并像这样构建我的数组,所以我想这可能会解决问题 - 想我还能做些什么来尝试减少执行时间吗?

标签: phpmysql

解决方案


根据每个人的评论等,我设法执行了一些事情,使我的查询运行得更快,并且不会使我的脚本崩溃。

1) 索引

我在我table_three的字段上创建了一个索引fit_model_id

CREATE INDEX fit_model ON `table_three` (`fit_model_id`);

这使我的 LIMIT 1 查询从 16 秒变为 0.03 秒执行时间(在 MYSQL CLI 中)。

但是,100 行左右的时间仍然比我想象的要长得多。

2) 外键

我创建了一个链接的外键table_onemodel_id= table_threefit_model_id使用以下查询:

ALTER TABLE `table_one`
ADD CONSTRAINT `model_id_fk_tbl_three`
FOREIGN KEY (`model_id`)
REFERENCES `table_three` (`fit_model_id`)

这绝对有帮助,但仍然觉得可以做更多的事情。

3) 优化表

然后我OPTIMIZE TABLE在这些表上使用:

  • table_one
  • 表三

然后,这使我的脚本工作和我的查询一如既往地快速。但是,我遇到的问题是一个大型数据集,所以我让查询在 MYSQL CLI 中运行,同时将每个脚本运行时间的 LIMIT 增加 1000 以帮助索引过程,在它开始崩溃之前一直到 30K 行。

CLI 用了 31 分 8 秒完成。所以我这样做了:

31 x 60 = 1860

1860 + 8 = 1868

1868 / 448476 = 0.0042

所以每一行需要 0.0042 秒才能完成——这在我看来已经足够快了。

感谢大家的评论和帮助我调试和解决问题:)


推荐阅读