我有一个查询选择节点表,然后加入一个标题表。这是通过首先加入节点ID和标题ID之间的中间表来完成的,这允许前两个表之间的多对多关系。两个连接都是内联的,因此只有具有正确配置和现有标题的节点才被选中。我相信这一切都是干净和高效的 - 问题如下:快速查询选择不在MySQL的另一个表中的所有记录
还有第四个表,它为节点提供了一个简单的层次结构; node_parents。每行有两个字段;节点ID和充当该节点的父节点的节点ID(node_id和parent_id)。有些节点没有在此数据库中配置子节点(即节点本身未在node_parents表的任何行中标记为父节点) - 这些是我试图选择的节点。
这些无子节点的附加标准是它们有一个特定的标题配置 - 因此子查询最初从node_titles选择,然后内部加入node_parents。子查询也有一个GROUP BY,因为有些节点是多个节点的父节点,所以它们的node_id将不必要地出现在结果中多次。我还应该指出,正因为如此,node_parents的主键是node_id和parent_id的组合。
查询:
SELECT `nodes`.`node_id`,
`titles`.`title`
FROM `nodes`
INNER JOIN `node_titles`
ON `nodes`.`node_id` = `node_titles`.`node_id`
INNER JOIN `titles`
ON `node_titles`.`title_id` = `titles`.`title_id`
WHERE `nodes`.`node_id` NOT IN
(
SELECT `node_titles`.`node_id`
FROM `node_titles`
INNER JOIN `node_parents`
ON `node_titles`.`node_id` = `node_parents`.`parent_id`
WHERE `node_titles`.`title_id` = 1
GROUP BY `node_titles`.`node_id`
)
AND `titles`.`title_id` = 1
表尺寸: 节点=〜32000个 node_titles =〜49000个 标题= 3个 node_parents =〜55000
的查询接受约16分钟来完成。任何人都可以提供任何指针?我曾尝试剖析查询 - 这没有任何长挂,但它确实重复这个循环什么好像每次选定行:
| executing | 0.000005 |
| Copying to tmp table | 0.515815 |
| Sorting result | 0.000053 |
| Sending data | 0.000028 |
我也曾尝试开沟子查询和使用LEFT JOIN与一个WHERE foo不是NULL,但是这仍然需要很长时间来处理 - 分析器宣称'复制到tmp表'的时间为180秒。
最终我怀疑这可能是一个索引问题 - 但无论哪种方式,我都会欣赏不会质疑查询实现的答案,除非他们正在追求可能的放缓原因(例如,是,标题和节点必须处于多对多关系)。谢谢大家,并提供更多信息!
您当前的查询只有在定义了'title = 1'(可能沿着其他标题)时才会选择无子节点。那是你想达到的目标吗? – Quassnoi 2011-04-21 11:44:36
@Quassnoi对不起,忘了在主要查询中包含一个附加的where子句,它应该停止有子节点的节点被选中。 – tjbp 2011-04-21 12:04:24
查看查询更新。 – Quassnoi 2011-04-21 12:18:42