我有一个 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_packet
限制。不必在单个语句中插入所有行。一次插入 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/