php - (内部)加入此表时导致此内存泄漏的原因是什么?
问题描述
我脑子里有 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,我可以分解查询并像这样构建我的数组,所以我想这可能会解决问题 - 想我还能做些什么来尝试减少执行时间吗?
解决方案
根据每个人的评论等,我设法执行了一些事情,使我的查询运行得更快,并且不会使我的脚本崩溃。
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_one
。model_id
= table_three
。fit_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 秒才能完成——这在我看来已经足够快了。
感谢大家的评论和帮助我调试和解决问题:)
推荐阅读
- spring - 从 Spring Initializer 下载的项目抛出运行时错误:创建 bean jpaMappingContext 时出错
- android - 在 viewpager 中更改选项卡的方法调用
- css - Bootstrap 4 - 导航栏搜索表单最小宽度
- reactjs - React 自动完成元素以及在列表中添加值(如果不存在)的选项
- node.js - 未找到 Socket.io 客户端错误 404
- aspnetboilerplate - 升级到 3.6.2 后 JSON 序列化程序不工作
- php - 限制对 PHP 上的管理按钮的访问
- c# - 如何执行取决于策略的多项操作?
- spring-boot - 收到消息 MessageDeliveryException: Dispatcher 没有订阅者时
- laravel-5.5 - Laravel 类型错误:函数参数太少