You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效将SQLite树形表加载为可便捷访问的树变量?

高效加载SQLite树状数据为可访问数组的方案

你的递归方法速度慢的核心原因是触发了数千次数据库查询——每处理一个节点就执行一次SQL,8000条数据会带来极大的数据库IO开销。最优方案是一次性拉取所有数据到内存,再在内存中构建树结构,只需要1次SQL查询,效率会大幅提升。

具体实现步骤

1. 一次性获取所有数据

先把整张表的数据一次性查出来,同时按PARENT和NAME排序,减少后续内存排序的工作:

// 只查询需要的字段(不要用SELECT *),进一步降低内存占用
$allData = Q("SELECT ID, PARENT, NAME /* 按需添加其他字段 */ FROM ORGCHART ORDER BY PARENT ASC, NAME ASC")->fetchAll();

2. 构建辅助映射数组

用两个数组做快速索引:

  • $nodeMap:以节点ID为键,存储完整节点数据,用于O(1)时间查找节点
  • $childrenMap:以父节点ID为键,存储该父节点下所有子节点的ID列表
$nodeMap = [];
$childrenMap = [];

foreach ($allData as $row) {
    $id = $row['ID'];
    $parentId = $row['PARENT'];
    
    $nodeMap[$id] = $row;
    
    if (!isset($childrenMap[$parentId])) {
        $childrenMap[$parentId] = [];
    }
    $childrenMap[$parentId][] = $id;
}

3. 构建树结构

可以选择递归或迭代方式,迭代方式更适合层级极深的树,避免栈溢出:

递归实现(代码简洁,适合层级不特别深的场景)
function buildTree($rootId, $nodeMap, $childrenMap) {
    $tree = [];
    // 遍历根节点下的所有子节点ID
    foreach ($childrenMap[$rootId] ?? [] as $childId) {
        $node = $nodeMap[$childId];
        // 递归获取子节点的子树
        $node['children'] = buildTree($childId, $nodeMap, $childrenMap);
        $tree[] = $node;
    }
    return $tree;
}

// 生成以PARENT=0为根的树结构
$allmap = buildTree(0, $nodeMap, $childrenMap);
迭代实现(避免栈溢出,适合大数据量+深层级场景)
function buildTreeIterative($rootId, $nodeMap, $childrenMap) {
    $tree = [];
    // 栈元素:[父节点ID, 父节点的子节点数组引用]
    $stack = [[$rootId, &$tree]];
    
    while (!empty($stack)) {
        list($parentId, $parentChildrenRef) = array_pop($stack);
        // 倒序遍历子节点ID,保证最终顺序和递归一致
        foreach (array_reverse($childrenMap[$parentId] ?? []) as $childId) {
            $childNode = $nodeMap[$childId];
            $childNode['children'] = [];
            $parentChildrenRef[] = $childNode;
            // 将子节点压入栈,处理它的子节点
            $stack[] = [$childId, &$parentChildrenRef[count($parentChildrenRef)-1]['children']];
        }
    }
    return $tree;
}

$allmap = buildTreeIterative(0, $nodeMap, $childrenMap);

效率优势

  • 仅1次SQL查询,彻底消除了多次数据库请求的IO开销
  • 内存操作的时间复杂度为O(n),远低于原递归查询的O(n²)
  • 提前在SQL中完成排序,比内存排序更高效

内容的提问来源于stack exchange,提问作者Michael Chourdakis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:43:26