首页 > 解决方案 > 如何避免for循环中的mysql查询

问题描述

我在 PHP 的苗条框架中开发了 JSON API。使用此 API,我将联系号码从我的移动设备发送到服务器。服务器将这些联系人保存在 MySQL 数据库中。

我使用具有 4 核 CPU、8 GB 内存的数字海洋托管来托管 API。为了进行压力测试,我向POSTAPI 发送了 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。

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_idseeder_id.

如您所见,我必须检查记录是否已经存在,如果是,则获取它的 id,否则创建一条新记录。因此,为了插入一个联系人,我在最坏的情况下运行 4 个查询,在最好的情况下运行 3 个,是的,这些查询循环运行。因此,对于 100 个联系人,它会是。4*100 = 400查询。这就是降低我的服务器速度的原因。

我希望我已经为您提供了足够的细节来理解我的问题,请提出一个解决方案,以解决我如何避免循环中的这些查询并实现我的目标。在提到批量插入之前,请检查我需要id创建的每条记录,例如contact。在批量插入中,获取已创建记录的 id 是另一个问题。

标签: phpmysqlapache

解决方案


您可以尝试INSERT IGNORE INTO这将自动删除您的支票,您可以将您的号码(手机)保留为您已经在做的唯一/主键。

这将删除您的第一个查询。

你的解释远远超出了理解。请大言不惭,并使其易于理解。

如果它返回播种机已经存在,那么我不插入这个播种机,否则我将记录插入到联系播种机表中。


推荐阅读