php - 重写时的数据库查询

标签 php mysql mysqli

我有一个 PHP 脚本,每 5 分钟运行一次,从 API 获取数据,然后将其写入 MySQL 表。我网站的用户(超过 300 名)可以通过数据表查询该数据,其他页面也会显示其中的一些数据。 PHP脚本获取API数据然后

foreach($array as $row)
{
    $query .= "INSERT INTO table_name 
    (
        col_name1, 
        col_name2, 
        col_name3, 
        col_name4, 
        col_name5
    ) 
    VALUES
    (
        '".$row["value1"]."', 
        '".$row["value2"]."', 
        '".$row["value3"]."', 
        '".$row["value4"]."', 
        '".$row["value5"]."'
    );";
}

mysqli_query($connect, "DELETE FROM table_name");

mysqli_multi_query($connect, $query);

每次脚本运行时,删除然后插入到该空表中。 该表有 1000 行,并且会随着时间的推移而增长。 我收到报告称数据表有时是空的,他们必须刷新几次才能显示任何内容。

是否有更好的方法来构建数据库、表和/或查询。

最佳答案

为每一行运行单独的插入语句将会非常慢。

运行多重插入会更有效,用一条语句插入多行。例如,使用一条语句插入四行。

INSERT INTO t (a,b,c) VALUES (?,?,?) ,(?,?,?) ,(?,?,?) ,(?,?,?)

一个潜在的缺点是,如果某一行由于错误而无法插入,则整个语句将回滚,并且不会插入任何行。

SQL语句的最大长度受max_allowed_pa​​cket限制。不必在单个语句中插入所有行。一次插入 10 行将显着减少语句执行次数。

假设表使用InnoDB存储引擎...

如果我们禁用自动提交,并在单个事务的上下文中运行 DELETE 语句和 INSERT 语句,那么对于其他 session 来说,表不会显示为“空”。其他 session 将继续查看表的内容,就像DELETE之前一样...直到COMMIT完成。

<小时/>

该代码模式似乎容易受到 SQL 注入(inject)攻击。 (尤其是使用多查询时,会出现很多肮脏的情况。

缓解 SQL 注入(inject)的最佳实践是使用带有绑定(bind)占位符的准备好的语句。

https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

<小时/>

编辑

作为替代方法,如果表具有主键或唯一键,请考虑

加载临时表(不是目标表)。

然后运行语句来应用更改以使目标表与临时表同步。我们将通过名称 source 来引用临时表。

--更新现有行

 UPDATE target t 
   JOIN source s
     ON s.id = t.id
    SET t.col = s.col 
      , t.foo = s.foo
      , t.bar = s.bar

--插入新行

INSERT INTO target
SELECT s.*
  FROM ( SELECT r.*
           FROM source r
             -- anti-join 
           LEFT
           JOIN target q
             ON q.id = r.id 
          WHERE q.id IS NULL
        ) s

--删除已删除的行

 DELETE t.*
   FROM target t
     -- anti-join
   LEFT
   JOIN source s
     ON s.id = t.id
  WHERE s.id IS NULL 

这避免了必须“清空”目标表,因此并发 SELECT 语句在目标表“同步”时仍将返回行。

针对目标表的 DML UPDATE/INSERT/DELETE 操作可以在单个事务的上下文中执行。

关于php - 重写时的数据库查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50659647/

相关文章:

php - 处理几个不同的表单输入字段 php

php - 如何以自动递增且不重复的方式发布ID

php - PHP 中动态 mysqli bind_param 参数的简单解决方案是什么?

php - 管理员用户名和密码错误

php - 从 1 个表格插入 2 个表格。 Mysql事务?

mysql - 使用 NodeJS、MySQL 测量查询执行时间

c# - 我如何使用 LIKE % C# 获取开始日期和结束日期

ruby-on-rails - 如何从mysql数据库转储数据到postgresql数据库?

php - MySQL 系统中的初期 bug

php - 通过 mysqli 运行多个查询时出现语法错误