brick / db
数据库工具库
Requires
- php: ^7.4 || ^8.0
- ext-pdo: *
Requires (Dev)
- php-coveralls/php-coveralls: ^2.0
- phpunit/phpunit: ^9.0
- vimeo/psalm: 5.15.0
This package is auto-updated.
Last update: 2024-09-03 00:02:15 UTC
README
数据库交互的辅助工具集合。
安装
此库可通过 Composer 安装。
composer require brick/db
要求
此库需要 PHP 7.4 或更高版本。
为了与 PHP 7.1、7.2 和 7.3 兼容,可以使用版本 0.1
。请注意,这些 PHP 版本已过时,不再受支持。如果您仍在使用这些 PHP 版本之一,应尽快考虑升级。
包概述
此包包含两个辅助工具:BulkInserter
和 BulkDeleter
。这些类基于 PDO
构建,允许您通过在每次查询中执行多个操作来加速数据库行插入和删除,同时提供干净的 OOP API。
BulkInserter
此类利用 MySQL、PostgreSQL 和 SQLite 中可用的扩展插入/多行语法。
它基本上取代了发送一系列查询的需求
INSERT INTO user (id, name, age) VALUES (1, 'Bob', 20); INSERT INTO user (id, name, age) VALUES (2, 'John', 22); INSERT INTO user (id, name, age) VALUES (3, 'Alice', 24);
通过一个单一、更快的查询
INSERT INTO user (id, name, age) VALUES (1, 'Bob', 20), (2, 'John', 22), (3, 'Alice', 24);
要使用它,请使用以下方式创建一个 BulkInserter
实例
- 您的
PDO
连接对象 - 您的表名
- 要插入的列名
- 每次查询中要执行的插入次数(可选,默认为 100)
示例
use Brick\Db\Bulk\BulkInserter; $pdo = new PDO(...); $inserter = new BulkInserter($pdo, 'user', ['id', 'name', 'age'], 100); $inserter->queue(1, 'Bob', 20); $inserter->queue(2, 'John', 22); $inserter->queue(3, 'Alice', 24); $inserter->flush();
当调用 flush()
或达到每次查询的插入次数时,queue()
方法才会执行操作。
注意:当仅排队插入时,queue()
返回 false
,当达到每次查询的插入次数并因此将批量刷新到数据库时,返回 true
。这可以用于监控批量的进度。
不要忘记在所有插入都已排队后调用 flush()
。否则,将导致记录未插入。
BulkDeleter
此类允许您一次删除多个记录。
它基本上取代了需要执行这些查询的需求
DELETE FROM user WHERE id = 1; DELETE FROM user WHERE id = 2; DELETE FROM user WHERE id = 3;
通过一个单一、更快的查询
DELETE FROM user WHERE (id = 1) OR (id = 2) OR (id = 3);
构造函数参数与 BulkInserter
相同。
出于明显的性能原因,用于标识记录的列列表应匹配表的主键或唯一索引。
示例
具有单列主键/唯一索引
use Brick\Db\Bulk\BulkDeleter; $pdo = new PDO(...); $deleter = new BulkDeleter($pdo, 'user', ['id']); $deleter->queue(1); $deleter->queue(2); $deleter->queue(3); $deleter->flush();
具有复合键
use Brick\Db\Bulk\BulkDeleter; $pdo = new PDO(...); $deleter = new BulkDeleter($pdo, 'user_product', ['user_id', 'product_id]); $deleter->queue(1, 123); $deleter->queue(2, 456); $deleter->queue(3, 789); $deleter->flush();
不要忘记在所有删除都已排队后调用 flush()
。否则,将导致记录未删除。
性能提示
为了从该库中获得最大性能,您应该
- 将操作包装在事务中
- 禁用准备语句仿真(
PDO::ATTR_EMULATE_PREPARES=false
)
这些建议结合可以提高每秒插入量达 50%。示例代码
$pdo = new PDO(...); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $inserter = new BulkInserter($pdo, 'user', ['id', 'name', 'age']); $pdo->beginTransaction(); $inserter->queue(...); // more queue() calls... $inserter->flush(); $pdo->commit();
库可以自动执行此操作,但出于以下原因而不执行
- 不应由第三方库修改您的 PDO 对象的配置
- 您应完全控制事务,何时开始它们以及何时提交它们
遵守限制
在提高每次查询的操作数量时要小心,因为您可能会遇到这些限制
- PHP 的 memory_limit
- MySQL 的 max_allowed_packet
如果您有权访问服务器的配置,则可以调整这些设置。但是,重要的是要对不同的批量大小进行基准测试,以确定最佳大小并查看提高服务器限制是否值得努力。在大多数情况下,每次查询插入100条记录应该至少提供最大吞吐量的80%。
有关更深入的分析,请参阅这篇文章。
MySQL还有一个限制,即每个语句最多有65535个占位符,这实际上将每次查询的操作数限制为floor(65535 / 列数)
。如果PDO模拟预定义语句,则此限制不适用。