php - 如何避免for循环中的mysql查询
问题描述
我在 PHP 的苗条框架中开发了 JSON API。使用此 API,我将联系号码从我的移动设备发送到服务器。服务器将这些联系人保存在 MySQL 数据库中。
我使用具有 4 核 CPU、8 GB 内存的数字海洋托管来托管 API。为了进行压力测试,我向POST
API 发送了 1000 个并发请求,每个请求的正文中有 500 个联系号码,突然服务器太忙于处理这些请求,它停止接受任何进一步的请求。我打开了 APACHE error.log
,我在那里看到了这条消息:
[Fri May 15 13:34:14.112205 2020] [mpm_prefork:error] [pid 42748] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
在看到这些日志后,我查看了由数字海洋提供的服务器控制面板统计数据,我看到 CPU 使用率为 64%,内存使用率为 16%,但磁盘 I/O 处于峰值。看到这个后,我知道我的 PHP 代码中有一些东西占用了 CPU 时间,并且从磁盘 I/O 使用情况来看,我首先想到的是我在 for 循环中运行的查询数量。我对其进行了搜索,现在发现在循环中运行查询是一种不好的做法。
已经两天了,我无法更改数据库设计以避免 for 循环中的那些查询。由于我已经提供了问题背景,现在让我解释一下如何将这些联系人保存在数据库中。
首先是我的数据库 ERD。
从请求正文中,我提取 JSON 联系人数组并在该联系人数组上循环。然后对于每个联系人,我使用此查询检查它是否已存在于我的数据库中。
Select id from contact where number = 'mobile number' and full_name = 'name' and country_id = 12;
我number
full_name
country_id
在数据库中创建了索引。如果联系人存在,则此查询返回id
该联系人的,否则返回FALSE
。如果我得到id
我在表中创建一条记录(contact_seeder
如果它不存在)。为了检查它是否已经存在,我contact_seeder
像这样查询表。
Select id from contact_seeder where contact_id = 12 and seeder_id = 2;
一个联系人只能有 1 条 'contact_seeder' 记录,而不是 1 条seeder_id
。这就是为什么我检查了 'contact_seeder' 是否存在于某些contact_id
和seeder_id
.
如您所见,我必须检查记录是否已经存在,如果是,则获取它的 id,否则创建一条新记录。因此,为了插入一个联系人,我在最坏的情况下运行 4 个查询,在最好的情况下运行 3 个,是的,这些查询循环运行。因此,对于 100 个联系人,它会是。4*100 = 400
查询。这就是降低我的服务器速度的原因。
我希望我已经为您提供了足够的细节来理解我的问题,请提出一个解决方案,以解决我如何避免循环中的这些查询并实现我的目标。在提到批量插入之前,请检查我需要id
创建的每条记录,例如contact
。在批量插入中,获取已创建记录的 id 是另一个问题。
解决方案
您可以尝试INSERT IGNORE INTO
这将自动删除您的支票,您可以将您的号码(手机)保留为您已经在做的唯一/主键。
这将删除您的第一个查询。
你的解释远远超出了理解。请大言不惭,并使其易于理解。
如果它返回播种机已经存在,那么我不插入这个播种机,否则我将记录插入到联系播种机表中。
推荐阅读
- javascript - 来自 API 的响应返回数据,状态未定义 - React.JS
- c# - ReUp:在 C# 中的表单之间传递多张图片
- csv - 如何在 swagger/yaml 文档上正确记录文本/csv 响应?
- django - 如何使用脚本文件填充 django 数据库?
- javascript - Google-Maps-React:将道具传递给 App.js 的问题
- javascript - Javascript:带有方法的对象与带有开关的函数
- android - 一次添加一个元素时如何在recyclerview中平铺单个元素?
- python - 模拟 Peewe 类不会返回值
- julia - 如何使`eval`使用特定路径来解决Julia中的`include`?
- multithreading - goroutines(以及运行它们的操作系统线程)在被 IO 绑定操作阻塞时如何表现?