5

我有表(大约 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:最大取决于行 < 70

PP:

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
4

5 回答 5

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
于 2012-09-21T15:33:15.827 回答
1

好吧,在第一种情况下,MySQL 需要创建一个中间结果,将其存储在内存中,然后对其进行迭代以查找表中所有相关的 id。在第二种方式中,假设您正确地在 id 和 parent id 上创建了一个索引,它只是直接找到索引,找到相关的行,然后立即将结果发回给您。

于 2012-09-21T15:29:15.553 回答
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
于 2012-09-21T16:15:32.360 回答
0

这是一个很长的镜头,但在第一种情况下,您有查询的 WHERE 部分的“IN”语句。也许 MySQL 会尝试优化查询,就好像有多个选项一样,而在第二种情况下,没有 IN 部分,所以编译后的查询对于数据库来说更直接——从而以更好的方式利用索引。

基本上,对于同一连接上的 2 个查询,执行查询的开销在这种情况下应该是最小且无关紧要的。查询解析器通常也不能很好地优化子查询。尝试使用 JOIN 代替(如果可能)。

于 2012-09-21T15:28:28.593 回答
0

一个EXPLAIN可能会为您提供更多关于这个问题的信息。

查看EXISTS或将您的查询重写为JOIN.

于 2012-09-21T15:30:33.820 回答