我有嵌套的set table(MySQL),里面有大约150万条记录。 表结构是:
id | name | root_id | lft | rgt | level
我需要获取字符串,包含所有父记录的名称和记录名称,我们称之为'full_name'。 例如,它将是
"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索引?我认为这对于这种情况来说是理想的解决方案。
我还尝试更新添加'full_name'字段的MySQL表,但我的更新请求将需要几天才能完成作业。总的来说这是个好主意吗?是否有可能使此更新足够快?
我在想,也许我应该转移到PostgreSQL并使用分层请求(我对这个数据库没有经验,所以不能确定)?
谢谢
答案 0 :(得分:0)
当您说您要更新表以添加full_name字段时,您是说您是单独为每条记录运行上述查询吗?
真的不应该那么慢,桌面上有适当的索引吗?
无论如何,只需运行一个实际查询即可更快地获取所有记录。这里的功能: http://www.sitepoint.com/hierarchical-data-database-2/
可以轻松修改,更新所有recrds。只是不是打印出缩进列表,循环的每次迭代都应该运行一个更新语句。除了维护$ 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列上添加索引,然后运行多表更新,以从temporally表更新主表。这样会更快,因为它不是零碎地更新主要索引,而是在一大批上进行。