Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP&;MySQL,快速连续多次检查行的有效方法?_Php_Mysql_Performance_Query Optimization - Fatal编程技术网

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

PHP&;MySQL,快速连续多次检查行的有效方法?,php,mysql,performance,query-optimization,Php,Mysql,Performance,Query Optimization,我面临着一个以前从未遇到过的挑战,很难找到一个有效的解决方案。(可能是因为我不是训练有素的程序员,也不知道所有的术语) 挑战: 我每天都需要使用一个数据源来维护mysql数据库。为此,需要检查记录是否存在,然后相应地更新或插入 这本身就足够简单,但运行数千条记录——对每条记录进行查询以检查其是否已存在于数据库中似乎效率很低 有没有比在我的数据提要中循环并对每个记录运行单个查询更有效的方法?也许是一种将它们准备成一个更大的查询的方法(假设这是一种更有效的方法) 我不确定这里是否需要一个代码示例,

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

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

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


有没有比在我的数据提要中循环并对每个记录运行单个查询更有效的方法?也许是一种将它们准备成一个更大的查询的方法(假设这是一种更有效的方法)

我不确定这里是否需要一个代码示例,但是如果有更多的信息我可以提供,请询问!我真的很感激你的建议


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

如果问题在于检查、插入和更新的性能

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';
否则


这取决于您必须加载多少“提要”行。如果是10条,那么一条记录一条记录(如mustafayelmer所示)可能并不太糟糕。一旦你进入100及以上的区域,我强烈建议使用基于集合的方法。在创建和加载staging表时会有一些开销,但这(非常)迅速地被需要执行的查询的减少和通过网络进行的往返量所抵消

简而言之,您要做的是:

-- 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
使您的数据更新

注:

  • 您可能希望将stagingTable的名称设置为“random”,以避免出现两个“load”并行运行的情况,并可能开始重新使用同一个表,从而产生各种奇怪的结果(和错误)。由于所有这些代码都是在php中“生成”的,所以您只需在tablename中添加一个时间戳或其他内容

  • 在MSSQL上,我将使用大容量插入机制加载临时表中的所有数据。它可以使用
    bcp
    批量插入
    。Net实际上有这个类。如果你不介意先写一个临时文件,然后从那里加载,或者你可以用它来做大的插入块,而不是一个接一个的插入块,谷歌搜索一下就会告诉我mysql有什么功能。不过,我会避免一次插入10k,而是每100或500左右插入一次,您需要测试什么是最有效的

PS:你需要在这里和那里调整一下我的语法,就像我说的,我更熟悉MSSQLST-SQL方言。此外,您还可以在暂存表direclty上使用
on duplicate key
方法,从而在一个命令中组合
UPDATE
INSERT
。[MSSQL为此使用
MERGE
,但它看起来会完全不同,所以我不想在这里包含它。]


祝你好运。

如果不了解更多数据或数据库的组织方式,就很难真正给出详细答案。如果您可以将数据源分组到逻辑组中,您也可以在查询中使用这些逻辑组,那么您可以将数据库的部分加载到一个数组中,对照该数组检查所有数据,并执行所需的任何更新,然后用数据库中的下一部分记录重写数组,并对提要中的下一个逻辑数据组重复上述操作。感谢Sgt的评论!我已经为你更新了更多的信息。就从数据库中预加载一个ID数组以与提要进行比较而言,可能有数十万条记录,而提要只包含一个较小的样本。谢谢您的回答!我刚刚对“复制键”做了一些研究,现在它对我来说很有意义。这正是我要寻找的=)比我使用的if/else更有效,代码也更好。还有一些东西需要学习,我很可能会把它作为最好的答案。干杯
-- 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