public function getExportList($map)
{
// 定义初始分页大小和最小分页大小
$initialPageSize = 1000;
$minPageSize = 100;
$pageSize = $initialPageSize;
// 计算可用内存(保留15%缓冲)
$memoryLimit = (int) ini_get('memory_limit') * 0.85;
$lastId = 0;
$allData = [];
$hasMoreData = true;
// 用于动态调整分页大小的变量
$lastBatchMemoryUsage = 0;
$avgRecordSize = 0;
while ($hasMoreData) {
// 动态调整分页大小
if ($lastBatchMemoryUsage > 0 && $avgRecordSize > 0) {
$currentMemory = memory_get_usage(true) / (1024 * 1024);
$availableMemory = $memoryLimit - $currentMemory;
// 基于剩余内存和记录大小计算安全分页大小
$safePageSize = max(
$minPageSize,
min(
$initialPageSize,
(int)($availableMemory / ($avgRecordSize * 1.5)) // 1.5倍安全系数
)
);
$pageSize = ($safePageSize < $pageSize) ? $safePageSize : $pageSize;
}
// 执行分页查询
$list = self::where($map)
->withoutField(['z_create_time', 'z_update_time'])
->where('z_id', '>', $lastId)
->order('z_id', 'asc')
->limit($pageSize)
->select();
if ($list->isEmpty()) {
break;
}
$listData = $list->toArray();
$batchCount = count($listData);
// 计算当前批次内存占用
$batchMemory = memory_get_usage(true);
foreach ($listData as $record) {
$allData[] = $record; // 直接添加减少内存操作
}
$batchMemory = (memory_get_usage(true) - $batchMemory) / (1024 * 1024);
// 更新内存跟踪指标
if ($batchCount > 0) {
$currentAvg = $batchMemory / $batchCount;
$avgRecordSize = ($avgRecordSize > 0)
? ($avgRecordSize * 0.7 + $currentAvg * 0.3) // 平滑平均
: $currentAvg;
$lastBatchMemoryUsage = $batchMemory;
}
// 更新迭代变量
$hasMoreData = ($batchCount === $pageSize);
if ($hasMoreData) {
$lastRecord = end($listData);
$lastId = (int)$lastRecord['z_id'];
reset($listData); // 重置数组指针
}
// 资源清理
unset($list, $listData);
if (gc_enabled()) {
gc_collect_cycles();
}
}
return $allData;
}
//导出14730条数据,需要34.05秒,字段有50个,全是非空状态,字段数量会影响响应时间,一般导出起飞无压力
public function getExportList($map)
{
$pageSize = 1000;
$lastId = 0;
$allData = [];
while (true) {
// 查询当前批次
$list = self::where($map)
->withoutField(['z_create_time', 'z_update_time'])
->where('z_id', '>', $lastId)
->order('z_id', 'asc')
->limit($pageSize)
->select();
// 无数据时终止循环
if ($list->isEmpty()) {
break;
}
$batch = $list->toArray();
$batchSize = count($batch);
// 直接追加数据(避免array_merge内存峰值)
foreach ($batch as $record) {
$allData[] = $record;
}
// 到达数据末尾
if ($batchSize < $pageSize) {
break;
}
// 更新最后ID
$lastId = (int)end($batch)['z_id'];
// 资源清理
unset($list, $batch);
if ($batchSize >= 500) { // 仅在大批次后回收
gc_collect_cycles();
}
}
return $allData;
}
//这个是34.59秒。其他有很多方法,正在尝试30秒内
版权属于:
小破孩
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
评论 (0)