我有桌子(大约80'000行),看起来像
id, parentId, col1, col2, col3...
1, null, 'A', 'B', 'C'
2, 1, ...
3, 1, ...
4, null, ...
5, 4, ...
(一级父母 - 仅限儿童)
我需要获取所有相关行 -
SELECT ...
FROM table
WHERE id = :id OR parentId = :id OR id IN (
SELECT parentId
FROM table
WHERE id = :id
)
但为什么这个请求工作缓慢而不是2请求 - 如果我先在php上获得parentId?
$t = executeQuery('SELECT parentId FROM table WHERE id = :Id;', $id);
if ($t) {
$id = $t;
}
$t = executeQuery('SELECT * FROM table WHERE id = :id OR parentId = :id ORDER BY id;', $id);
PS:max取决于行数< 70
PPS:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY product ALL PRIMARY,parentId NULL NULL NULL 73415 Using where
2 DEPENDENT SUBQUERY product const PRIMARY,parentId PRIMARY 4 const 1
答案 0 :(得分:2)
更改IN
以获得相等的=
SELECT ...
FROM table
WHERE id = :id OR parentId = :id OR id = (
SELECT parentId
FROM table
WHERE id = :id
)
或将其更改为加入:
SELECT ...
FROM table
inner join (
SELECT parentId
FROM table
WHERE id = :id
) s on s.parentID = table.id or s.parentID = table.parentID
答案 1 :(得分:1)
嗯,在第一种情况下,MySQL需要创建一个中间结果,将其存储在内存中,然后迭代它以查找表中的所有相关id。在第二种方式中,假设您正确地在id和父ID上创建了一个索引,它只是直接转向索引,找到相关的行,并立即将结果发回给你。
答案 2 :(得分:1)
UNION在这种情况下的工作速度更快
这允许第一次查询用户UNION INDEX,第二次只使用内部联接,然后合并结果。
SELECT *
FROM `table`
WHERE id = :id OR parentId = :id
UNION
SELECT t1.*
FROM `table` t1 JOIN `table` t2 ON t2.parentId = t1.id AND t2.id = :id
答案 3 :(得分:0)
这是一个很长的镜头,但在第一种情况下,你有查询的WHERE部分的“IN”语句。也许MySQL试图优化查询,好像会有多个选项,而在第二种情况下没有IN部分,因此编译后的查询对数据库来说更直接 - 从而以更好的方式利用索引。
基本上对于同一连接上的2个查询,执行查询的开销应该是最小的,并且在这种情况下是相关的。查询解析器通常也不能非常优化子查询。尝试使用JOIN(如果可能)。
答案 4 :(得分:0)
EXPLAIN
可能会为您解决问题。
查看EXISTS
,或将您的查询重写为JOIN
。