【问题标题】:Making faster MySQL PHP queries进行更快的 MySQL PHP 查询
【发布时间】:2014-03-20 14:53:04
【问题描述】:

我有一个 CSV 文件,其中包含需要添加或更新的产品(如果存在)并保留旧产品,即使它已从列表中删除。

我有一个这样的循环:

while (($data = fgetcsv($handle, 1000, ";")) !== FALSE)

效果很好,我从中分配了几个这样的变量:

$price = htmlspecialchars(mysql_real_escape_string($data[2]), ENT_QUOTES, 'utf-8' );

在我设置了我需要的 4 个变量之后,我像这样查询 MySQL:

mysql_query("SELECT * FROM products WHERE productid = '$prodid' AND supplier = 'SUPPLIER1'")

如果结果为 1 或更多,我们只需更新它

            mysql_query("UPDATE tuotteet SET 
                        supplier = 'SUPPLIER1',
                        product = '$product',
                        prodid = '$prodid',
                        ean = '$ean',
                        price = '$price' WHERE prodid= '$prodid' AND supplier = 'SUPPLIER1'") or die(mysql_error());

如果从数据库中找不到产品,我们会进行另一个查询 INSERT。问题是这是一种非常缓慢的方法,需要花费很多分钟才能完成大约 10000 条产品线。

这有什么关系吗?

【问题讨论】:

  • 您可以尝试预先缓存您知道的数据,然后使用 PHP 从预先缓存的数据中进行比较,并在需要时使用批量查询进行更新。
  • 为什么不使用 INSERT.... ON DUPLICATE KEY.... 而不是 SELECT 后跟 INSERT 或 UPDATE?

标签: php mysql


【解决方案1】:

在开始该过程之前,我会在数据库中查询数据库中的所有 product_id,然后将它们存储在字典中。
然后,开始处理 csv 文件。 对于每条记录,只需询问字典是否有带有当前 product_id 的键。

这样做,您不必为 csv 中的每条记录访问数据库。

【讨论】:

  • 我喜欢这种方法,结合 Diamondo25 对批量查询的建议。有关如何批量插入的示例,请参见此处接受的答案:stackoverflow.com/questions/12960569/mysql-bulk-insert-via-php
  • 此方法有效,除非 CSV 文件的大小超过您的 PHP 最大内存限制。
  • 你是对的,如果是这样,你可以随时在 php.ini 上更改它。
【解决方案2】:

我遇到了类似的问题。最好的解决方案是构建一个单一的查询。这是Python中的代码:

# data to updload in a dictionary {id, new_value}
dict = {2:1001,4:251}

ids = [] 
sql = "UPDATE tabla1 SET value = CASE id "    

for key in dict:
    sql = sql + 'WHEN '+str(key)+' THEN '+str(dict[key])+ '\n\t'
    ids.append(key)
ids_string = ', '.join(map(str, ids))
sql = sql + "END WHERE id IN ("+ids_string+")"
print sql

【讨论】:

  • 我会使用短语“一个解决方案”而不是“最佳解决方案”。
  • 那么告诉我,您认为最好的解决方案是什么?还是更好的?
  • “最佳解决方案”不是任何人在回答此类开放式问题时都应使用的术语,因为没有明确的最佳解决方案。我认为 Esteban 的 ID 缓存比动态 SQL 方法更好。我还认为,由于带宽和超时限制,您的单查询解决方案对于超过一百条左右的记录都会失败。
  • 您的代码示例也存在很大缺陷。它不会在 Python 中编译,也不会产生健全的 SQL。特别是,sql = sql + "WHEN %d THEN %d ", key, key 这行毫无意义。如果您可以修复您的示例,以便它编译并发布一些有用的示例输出。
  • 抱歉,该行已被评论,只需再次评论,一切都会正常进行。 (已编辑)我已经用数百条记录对其进行了测试,并且工作正常。当我们要更新数千行时(这不太可能),我们可以将其划分为一些“单个查询”
【解决方案3】:

使用LOAD DATA 会更快、更高效,并且需要更少的代码:

LOAD DATA LOCAL INFILE 'myinput.csv'
 REPLACE INTO TABLE tuotteet

您只需确保在列(prodid, supplier) 上定义了主键或唯一键。 LOAD DATA 将使用它来判断该行是否已经存在并且需要更新,或者该行是否不存在并且需要作为新行插入。

那么你就不需要使用 fgetcsv(),你不需要做任何转义,你不需要 SELECT 或 UPDATE 或 INSERT,它的运行速度应该快 10 倍左右。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 2012-06-29
    • 2012-05-27
    • 1970-01-01
    相关资源
    最近更新 更多