brick/db

数据库工具库

维护者

详情

github.com/brick/db

来源

问题

资助包维护!
BenMorel

0.2.0 2023-09-01 19:56 UTC

This package is auto-updated.

Last update: 2024-09-03 00:02:15 UTC


README

数据库交互的辅助工具集合。

Build Status Coverage Status Latest Stable Version Total Downloads License

安装

此库可通过 Composer 安装。

composer require brick/db

要求

此库需要 PHP 7.4 或更高版本。

为了与 PHP 7.1、7.2 和 7.3 兼容,可以使用版本 0.1。请注意,这些 PHP 版本已过时,不再受支持。如果您仍在使用这些 PHP 版本之一,应尽快考虑升级。

包概述

此包包含两个辅助工具:BulkInserterBulkDeleter。这些类基于 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 对象的配置
  • 您应完全控制事务,何时开始它们以及何时提交它们

遵守限制

在提高每次查询的操作数量时要小心,因为您可能会遇到这些限制

如果您有权访问服务器的配置,则可以调整这些设置。但是,重要的是要对不同的批量大小进行基准测试,以确定最佳大小并查看提高服务器限制是否值得努力。在大多数情况下,每次查询插入100条记录应该至少提供最大吞吐量的80%。

Extended inserts benchmark

有关更深入的分析,请参阅这篇文章

MySQL还有一个限制,即每个语句最多有65535个占位符,这实际上将每次查询的操作数限制为floor(65535 / 列数)。如果PDO模拟预定义语句,则此限制不适用。