0

我有嵌套的集合表(MySQL),里面有大约 150 万条记录。表结构为:

id | name | root_id | lft | rgt | level

我需要获取字符串,其中包含所有父记录的名称加上记录名称,我们称之为“全名”。例如,它将是

"United States, California, Los Angeles"

为“洛杉矶”唱片。

我可以使用以下命令查询 ONE 记录的所有名称:

SELECT parent.name
FROM location AS node,
     location AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND parent.root_id=node.root_id AND node.id=:id
ORDER BY parent.level

并使用 implode() 构建 full_name

但是此请求仅适用于一条记录,对于多个呼叫而言工作速度太慢。所以现在我想将 'full_name' 添加到 Sphinx 索引(或者可能直接添加到 MySQL)。

问题:

  • 是否可以构造这样的 sql 查询,为每条记录选择“full_name”以将其放入 Sphinx 索引?我认为这将是这种情况的理想解决方案。

  • 我还尝试更新 MySQL 表,添加“full_name”字段,但我的更新请求需要几天时间才能完成。这是个好主意吗?是否有可能使此更新足够快?

  • 我在想,也许我应该转移到 PostgreSQL 并使用分层请求(我没有使用这个数据库的经验,所以不能确定)?

谢谢

4

1 回答 1

0

当您说您正在更新表以添加 full_name 字段时,您的意思是您正在为每条记录单独运行上述查询吗?

真的不应该那么慢,你的表上有正确的索引吗?

无论如何,您可以通过只运行一个实际查询来更快地获取所有记录。这里的功能: http ://www.sitepoint.com/hierarchical-data-database-2/

可以轻松修改,更新所有记录。与其打印一个缩进列表,循环的每次迭代都应该运行一个更新语句。除了维护 $right 数组外,还需要维护一个字符串列表。在哪里添加/删除正确的同时添加另一个数组。

// start with an empty $right stack
$right = array();
$names = array();

// now, retrieve whole tree
$result = mysql_query('SELECT id, name, full_name, lft, rgt FROM location ORDER BY lft ASC');

// update each row
while ($row = mysql_fetch_array($result)) {
    // only check stack if there is one
    if (count($right)>0) {
        // check if we should remove a node from the stack
        while ($right[count($right)-1]<$row['rgt']) {
            array_pop($right);
            array_pop($names);
        }
    }

    // add this node to the stack
    $right[] = $row['rgt'];
    $names[] = $row['name'];

    if (empty($row['full_name'])) {
        mysql_query("UPDATE location SET full_name='".mysql_real_escape_string(implode(', ',$names))."' WHERE id=".intval($row['id']));
    }
}

如果这仍然很慢,而不是更新原始表,将 full_name(连同 id)插入到一个没有任何索引的新表中。更改表以在 id 列上添加索引,然后运行多表更新,以从临时表更新主表。这会更快,因为它不是零星地更新主要索引,而是在一个大批量上进行。

于 2012-12-15T00:11:51.657 回答