jotagp / insert-multiple
一个简单的PHP包,用于将多个记录插入MySQL/MariaDB数据库。
README
摘要
- 介绍
1.1 什么是
1.2 为什么
1.3 许可证 - 开始使用
2.1 依赖项
2.2 安装
2.3 使用
2.4 方法
2.5 示例 - 享受
1. 介绍
1.1 什么是
这是一个简单的PHP包,可以将多个数据插入MySQL/MariaDB数据库。
1.2 为什么
创建此包的目的是为了减少数据插入时间。为了理解问题的严重性,让我们假设我们想要遍历一个列表中的项并将它们插入到数据库中。
// example with tradicional insert foreach ($list as $item) { $insert = "INSERT INTO `table1`(`numbers`, `description`) VALUES ({$item['number']}, '{$item['description']}'); $connection->query($insert) or die ($connection->error); }
上面的例子是可行的。然而,当处理大量数据时,传统的插入方法并不可行。这是因为它一次只插入一条记录。所以,如果你有100,000条记录,将有100,000次插入,相应地,将有100,000次硬盘访问以持久化这些数据,这将花费很长时间(当然,这取决于你的数据大小)。一个“方法”是手动控制数据库的事务,如下所示:
// example with tradicional insert and transaction control $connection->begin_transaction(); foreach ($list as $item) { $insert = "INSERT INTO `table1`(`numbers`, `description`) VALUES ({$item['number']}, '{$item['description']}'); $connection->query($insert) or die ($connection->error); } $connection->commit();
然而,这种方法仍然不能从根本上解决我们的问题,因为时间上的节省并不显著。那么我们该怎么办呢?简单!进行多次插入
// example with manually multiple insert $connection->begin_transaction(); $insert = "INSERT INTO `table1`(`numbers`, `description`) VALUES "; foreach ($list as $item) { $values[] = "({$item['number']}, '{$item['description']}')"; // concat new values } $insert .= implode(", ", $values); // join values separete by comma $connection->query($insert) or die ($connection->error); $connection->commit();
然而(总是有一个“然而”,对吧?),银行允许的交易限制,当设置一个非常广泛的查询时,这个限制很容易达到。这就是这个包发挥作用的地方。它将根据银行的能力将你的值分成N个多次插入槽位
// example with package $insert = new insert_multiple($connection, "table1"); foreach ($list as $item) { $insert->push($item); // concat new values } $insert->exec(); // run inserts
就这么简单。
1.3 许可证
此代码受MIT许可证许可。
2. 开始使用
2.1 依赖项
此库只依赖于
2.2 安装
运行以下命令
composer require jotagp/insert-multiple
2.3 使用
将依赖项包含到你的PHP项目中
require 'vendor/autoload.php'; use jotagp\insert_multiple\insert_multiple; $connection = new mysqli('host', 'user', 'pass', 'database'); $insert_multiple = new insert_multiple($connection, 'table-name');
2.4 方法
有三种可能的方法
push($associative_array)
此方法用于将新值包括在插入中。请注意,预期的参数是一个关联数组,其中数组的索引必须始终引用要插入的表的属性。未指定的属性将使用各自的默认值。
exec()
此方法将你的插入分割成N个多次插入,然后运行,始终考虑你的数据库实例允许的事务量(max_allowed_package)。也就是说,在一个包含100万条记录的插入中,假设函数将创建10个多次插入,每个插入10万条记录。
config($associative_array)
此方法允许你编辑对象的一些行为。可能的配置(目前)有
- update_if_exists: 如果存在相应的键,则更新记录。
- fields_to_update: 在update_if_exists内部,你可以指定应更新的哪些字段。
- concat_new_values: 允许将新值连接到现有值。
- skip_if_already_exists: 保留已存在的值,忽略新值。
- skip_if_new_is_empty: 如果新的值为空或为null,则保留已存在的值。
- insert_multiple: 如果为false,则每次插入一条记录。
2.5 示例
将10万条随机数据插入数据库。考虑以下数据结构
DROP DATABASE IF EXISTS `0temp`; CREATE DATABASE `0temp`; USE `0temp`; DROP TABLE IF EXISTS `table1`; CREATE TABLE `table1` ( `number` int(11) NOT NULL AUTO_INCREMENT, `description` varchar(255) DEFAULT NULL, PRIMARY KEY (`number`) )
然后
<?php require 'vendor/autoload.php'; use jotagp\insert_multiple\insert_multiple; $connection = new mysqli('localhost','root', 'root', '0temp') or die($connection->error); $insert_multiple = new insert_multiple($connection, 'table1'); // generate randon numbers, between 1 and 1000 $count = 0; while ($count < 100000) { $list[] = ['value' => rand(1, 1000)]; $count += 1; } // insert multiple echo "\nStart at: ". Date('Y-m-d H:i:s') . "\n[ "; $count = 0; // for print a simple log foreach ($list as $key => $item) { $table1 = []; // clean the associative array $table1['number'] = $key; // the 'number' index, matches the database attribute $table1['descriptions'] = $item['value']; // the 'number' index, matches the database attribute // magic is here $insert_multiple->push($table1); // push the associative array $count += 1; if ($count % 1000 == 0) echo "#"; if ($count % 10000 == 0) echo " ". $count ." "; } // magic is here two $insert_multiple->exec(); // update multiple $update_multiple = new insert_multiple($connection, 'table1'); $update_multiple->config([ 'update_if_exists' => [ 'fields_to_update' => [ 'description' ] // 'concat_new_values' => true, // 'skip_if_already_exists' => true, // 'skip_if_new_is_empty' => true ] ]); echo "\nStart at: ". Date('Y-m-d H:i:s') . "\n[ "; $count = 0; // for print a simple log foreach ($list as $key => $item) { $table1 = []; $table1['number'] = $key; // important! when you go update a row, remember set the key property (in this case, field number) $table1['descriptions'] = 'data updated by jotagp lib'; $update_multiple->push($table1); $count += 1; if ($count % 1000 == 0) echo "#"; if ($count % 10000 == 0) echo " ". $count ." "; } $update_multiple->exec(); echo "]\nfinished at: ". Date('Y-m-d H:i:s') . "\n"; ?>
3. 享受
感谢您耐心阅读到这里。希望这个包能帮助您在日常工作中获得更好的性能。
如果您需要帮助或有任何建议,我随时为您服务。您可以通过LinkedIn联系我。