PHP和MySQL,快速连续多次检查行的有效方法?

Posted

技术标签:

【中文标题】PHP和MySQL,快速连续多次检查行的有效方法?【英文标题】:PHP & MySQL, efficient way to check for rows many times in quick succession? 【发布时间】:2016-06-05 00:39:36 【问题描述】:

我面临着前所未有的挑战,并且难以找到有效的解决方案。 (可能是因为我不是受过训练的程序员,也不知道所有的术语)。

挑战:

我有一个数据源,我需要每天使用它来维护一个 mysql 数据库。为此,需要检查记录是否存在,然后相应地更新或插入。

这本身就很简单,但是要为数千条记录运行它——对每条记录进行查询以检查它是否已经存在于数据库中似乎效率很低。


有没有比遍历我的数据馈送并为每条记录运行单独查询更有效的方法?也许是一种以某种方式将它们准备成一个更大的查询的方法(假设这是一种更有效的方法)。

我不确定这里是否需要代码示例,但如果我可以提供更多信息,请尽管询问!我非常感谢任何建议。


编辑:

@Sgt AJ - 数据馈送中的每条记录都有许多不同的列,但它们由一个 ID 索引。我会在数据库中检查该 ID 以查看是否存在记录。在这种情况下,我只更新一个表,尽管是一个大表(30 多列,主要是文本)。

【问题讨论】:

在不了解数据或数据库组织方式的情况下,很难真正为您提供任何详细的答案。如果您可以将数据馈送分组到您也可以在查询中使用的逻辑组中,也许您可​​以将数据库的部分加载到一个数组中,根据该数组检查所有数据,并执行您需要的任何更新,然后使用重写数组数据库中记录的下一部分,并为提要中的下一个逻辑数据组重复。 感谢中士的评论!我已经为您更新了更多信息。就从数据库中预加载一组 ID 以与提要进行比较而言,可能有数十万条记录,而提要仅包含较小的样本。 【参考方案1】:

有什么问题;

如果问题是检查、插入和更新的性能;

insert into your_table
(email, country, reach_time)
values ('mike@gmail.com','Italy','2016-06-05 00:44:33')
on duplicate key update reach_time = '2016-06-05 00:44:33';

我认为,您的密钥是电子邮件


旧式,不要使用

如果电子邮件存在

update your_table set
reach_time = '2016-06-05 00:44:33'
where email = 'mike@gmail.com';

其他

insert into your_table
(email, country, reach_time)
values ('mike@gmail.com','Italy','2016-06-05 00:44:33')

【讨论】:

感谢您的回答!我刚刚对“重复密钥”进行了一些研究,现在对我来说很有意义。这正是我正在寻找的 =) 比我使用的 if/else 更有效,并且代码更好。还有几件事要学习,然后我可能会将其作为最佳答案进行检查。干杯!【参考方案2】:

这取决于您必须加载多少“提要”行。如果它像 10 条记录,那么逐条记录(如 mustafayelmer 所示)可能还不错。一旦你进入 100 及以上区域,我强烈建议使用基于集合的方法。创建和加载临时表有一些开销,但这(非常)很快被需要执行的查询的减少和网络上的往返次数所抵消。

简而言之,你要做的是:

-- create new, empty staging table
SELECT * INTO stagingTable FROM myTable WHERE 1 = 2

-- adding a PK to make JOIN later on easier
ALTER TABLE stagingTable ADD PRIMARY KEY (key1)

-- load the data either using INSERTS or using some other method
-- [...] 

-- update existing records
UPDATE myTable
   SET field1 = s.field1,
       field2 = s.field2,
       field3 = s.field3
  FROM stagingTable s
 WHERE s.key1 = myTable.key1

-- insert new records
INSERT myTable (key1, field1, field2, field3)
SELECT key1, field1, field2, field3
  FROM stagingTable new
 WHERE NOT EXISTS ( SELECT * 
                      FROM myTable old
                     WHERE old.key1 = new.key1 )

-- get rid of staging table again
DROP TABLE stagingTable

更新您的数据。

注意事项:

1234563 )。由于所有这些代码都是在 php 中“生成”的,因此您可以简单地在表名中添加时间戳或其他内容。

在 MSSQL 上,我将使用批量插入机制加载暂存表中的所有数据。可以使用bcpBULK INSERT; .Net 实际上有 SqlBulkCopy 类。一些快速的谷歌搜索告诉我mysql有mysqlimport,如果你不介意先写入一个临时文件然后从那里加载,或者你可以使用this来做大的INSERT块而不是一个接一个。不过,我会避免一次插入 10k 次,而是每 100 次或 500 次左右插入一次,您需要测试最有效的方法。

PS:你需要在这里和那里稍微调整一下我的语法,就像我说的那样,我更熟悉 MSSQLs T-SQL 方言。此外,您可以在临时表直接使用on duplicate key 方法,从而将UPDATEINSERT 组合在一个命令中。 [MSSQL 为此使用MERGE,但它看起来完全不同,所以我不会费心在此处包含它。]

祝你好运。

【讨论】:

以上是关于PHP和MySQL,快速连续多次检查行的有效方法?的主要内容,如果未能解决你的问题,请参考以下文章

iOS UIButton 禁止连续点击问题/快速点击/重复点击/多次点击 2021-12-03

如何将包含 200,00 行的巨大 CSV 文件导入 MySQL(异步且快速)?

快速连续多次创建 UIAlertView

防止快速连续点击button多次执行相同操作

PHP mysql_num_rows() 函数 返回结果集中行的数目。

检查mysql表php中是不是存在任何记录