PHP如何使用XlsWriter实现百万级数据导入导出

 更新时间:2025年02月19日 08:45:35   作者:程序员阿凡提  
这篇文章主要为大家详细介绍了PHP如何使用XlsWriter实现百万级数据导入导出,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下

在PHP中使用 XlsWriter(如 xlswriter 扩展)处理百万级数据的导入导出,需重点解决内存占用和性能问题。

以下是分步骤的实现方案:

一、环境准备

1 安装 xlswriter 扩展

从PECL安装:

pecl install xlswriter

在 php.ini 中启用扩展:

extension=xlswriter.so

2 调整PHP配置

处理大数据时需增加内存和执行时间限制:

memory_limit = 1024M
max_execution_time = 3600

二、百万级数据导出(Excel)

核心思路

流式写入:避免一次性加载所有数据到内存。

分页查询:从数据库分批读取数据。

直接输出到浏览器:减少临时文件占用。

代码实现

<?php
// 1. 初始化Excel对象
$config = ['path' => '/tmp']; // 临时目录(可选)
$excel = new \Vtiful\Kernel\Excel($config);
$file = $excel->fileName('export.xlsx')->header(['ID', 'Name', 'Email']);
 
// 2. 设置HTTP头直接下载
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="export.xlsx"');
header('Cache-Control: max-age=0');
$file->output();
 
// 3. 连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
 
// 4. 分页查询并写入数据
$pageSize = 10000; // 每页数据量
$page = 1;
do {
    $offset = ($page - 1) * $pageSize;
    $stmt = $pdo->prepare("SELECT id, name, email FROM users LIMIT :offset, :limit");
    $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
    $stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
    $stmt->execute();
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
 
    if (empty($data)) {
        break;
    }
 
    // 写入当前页数据
    foreach ($data as $row) {
        $file->data([$row['id'], $row['name'], $row['email']]);
    }
 
    $page++;
    ob_flush(); // 刷新输出缓冲区
    flush();
} while (true);
 
// 5. 结束写入
$file->output();

关键点

分页查询:通过 LIMIT 分批拉取数据,避免一次性加载百万数据。

流式输出:直接输出到浏览器,减少内存占用。

缓冲区刷新:使用 ob_flush() 和 flush() 实时推送数据到客户端。

三、百万级数据导入(Excel到数据库)

核心思路

分块读取Excel:避免一次性加载整个文件。

批量插入:使用事务和批量SQL减少数据库操作次数。

错误处理:记录错误数据,避免单条失败导致全部回滚。

代码实现

<?php
// 1. 上传文件处理
$uploadFile = $_FILES['file']['tmp_name'];
if (!is_uploaded_file($uploadFile)) {
    die('非法文件');
}
 
// 2. 初始化Excel读取器
$excel = new \Vtiful\Kernel\Excel();
$excel->openFile($uploadFile);
$sheet = $excel->getSheet();
 
// 3. 连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
$pdo->beginTransaction();
 
// 4. 分块读取并插入
$batchSize = 5000; // 每批插入量
$batchData = [];
$currentRow = 0;
 
try {
    while ($row = $sheet->nextRow()) {
        $currentRow++;
        if ($currentRow === 1) {
            continue; // 跳过标题行
        }
 
        // 数据校验(示例)
        if (empty($row[1]) || !filter_var($row[2], FILTER_VALIDATE_EMAIL)) {
            error_log("Invalid data at row $currentRow: " . json_encode($row));
            continue;
        }
 
        // 构建批量插入数据
        $batchData[] = [
            'id' => $row[0],
            'name' => $row[1],
            'email' => $row[2]
        ];
 
        // 批量插入
        if (count($batchData) >= $batchSize) {
            insertBatch($pdo, $batchData);
            $batchData = [];
        }
    }
 
    // 插入剩余数据
    if (!empty($batchData)) {
        insertBatch($pdo, $batchData);
    }
 
    $pdo->commit();
    echo "导入成功!";
} catch (Exception $e) {
    $pdo->rollBack();
    echo "导入失败: " . $e->getMessage();
}
 
// 批量插入函数
function insertBatch($pdo, $data) {
    $sql = "INSERT INTO users (id, name, email) VALUES ";
    $values = [];
    $placeholders = [];
    foreach ($data as $item) {
        $values[] = $item['id'];
        $values[] = $item['name'];
        $values[] = $item['email'];
        $placeholders[] = '(?, ?, ?)';
    }
    $sql .= implode(', ', $placeholders);
    $stmt = $pdo->prepare($sql);
    $stmt->execute($values);
}

关键点

分块读取:逐行读取Excel,避免内存爆炸。

事务提交:批量插入后提交事务,减少数据库压力。

错误跳过:记录错误行,避免单条数据错误导致整体失败。

四、性能优化技巧

1 索引优化:

在导入前移除索引,导入完成后重新创建。

使用 ALTER TABLE ... DISABLE KEYS 和 ALTER TABLE ... ENABLE KEYS(MyISAM引擎)。

2 调整MySQL配置:

innodb_buffer_pool_size = 2G
innodb_flush_log_at_trx_commit = 0

3  压缩Excel文件:

$file = $excel->fileName('export.xlsx')->setCompressionLevel(6);

五、注意事项

内存监控:使用 memory_get_usage() 实时监控内存。

超时处理:通过 set_time_limit(0) 禁用脚本超时。

日志记录:记录导入导出的进度和错误。

到此这篇关于PHP如何使用XlsWriter实现百万级数据导入导出的文章就介绍到这了,更多相关PHP XlsWriter数据导入导出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • PHP使用Curl实现模拟登录及抓取数据功能示例

    PHP使用Curl实现模拟登录及抓取数据功能示例

    这篇文章主要介绍了PHP使用Curl实现模拟登录及抓取数据功能,结合实例形式分析了php使用curl进行登陆、验证、cookie操作与数据抓取等相关实现技巧,需要的朋友可以参考下
    2018-04-04
  • PHP的PDO常用类库实例分析

    PHP的PDO常用类库实例分析

    这篇文章主要介绍了PHP的PDO常用类库,结合实例形式分析了PDO类库常见的连接,初始化及增删改查等操作技巧,需要的朋友可以参考下
    2016-04-04
  • Laravel实现autoload方法详解

    Laravel实现autoload方法详解

    本文给大家讲解的是在laravel中是怎么实现autoload的?分析之后才发现,真的是很巧妙,下面就来给大家详细说明下
    2017-05-05
  • php获取参数的几种方法总结

    php获取参数的几种方法总结

    本篇文章要是对php获取参数的几种方法进行了总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-02-02
  • php-fpm开启状态统计的方法详解

    php-fpm开启状态统计的方法详解

    这篇文章主要给大家介绍了php-fpm开启状态统计的方法,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-06-06
  • PHP实现过滤各种HTML标签

    PHP实现过滤各种HTML标签

    在做项目的过程中,我们经常需要用到过滤一些html标签来实现提高数据的安全性,其实就是删除那些对应用程序有潜在危害的数据。它用于去除标签以及删除或编码不需要的字符。
    2015-05-05
  • php准确获取文件MIME类型的方法

    php准确获取文件MIME类型的方法

    这篇文章主要介绍了php准确获取文件MIME类型的方法,涉及php针对文件属性操作的相关技巧,需要的朋友可以参考下
    2015-06-06
  • php提取字符串中网站url地址的方法

    php提取字符串中网站url地址的方法

    这篇文章主要介绍了php提取字符串中网站url地址的方法,可通过正则匹配查找并提取出URL地址,需要的朋友可以参考下
    2014-12-12
  • php判断str字符串是否是xml格式数据的方法示例

    php判断str字符串是否是xml格式数据的方法示例

    这篇文章主要介绍了php判断str字符串是否是xml格式数据的方法,结合实例形式较为详细的分析了php采用自定义函数针对xml格式数据进行验证的相关操作技巧,需要的朋友可以参考下
    2017-07-07
  • PHP封装的数据库模型Model类完整示例【基于PDO】

    PHP封装的数据库模型Model类完整示例【基于PDO】

    这篇文章主要介绍了PHP封装的数据库模型Model类,结合实例形式分析了php基于PDO针对mysql数据库常见增删改查、统计、判断等相关操作封装与使用技巧,需要的朋友可以参考下
    2019-03-03

最新评论