2017-06-22 65 views
1

这是工作的MySQL查询,是否可以将此转换为单个平面连接查询以提高性能?而不是使用下面的子查询。由于将子查询转换为加入查询

SELECT * from catAtt ca LEFT JOIN att a ON ca.attId = a.attId 
WHERE ca.catId = 53 AND a.attCatId = 
(
SELECT DISTINCT eav.catId FROM ent LEFT JOIN eav ON ent.entId = eav.entId 
WHERE ent.key = 'somekey' 
) 

回答

2

我会从简化查询开始。由于where子句,您的left join都是内连接。此外,子查询中不需要select distinct

select ca.*, att.* 
from catAtt ca join 
    att a 
    on ca.attId = a.attId 
where ca.catId = 53 and 
     a.attCatId = (select eav.catId 
        from ent join 
         eav 
         on ent.entId = eav.entId 
        where ent.key = 'somekey' 
        ); 

这表明使用索引:catAtt(catId, attId)att(attId, attCatId)ent(key, entId)eav(entId, catId)

您还可以将where中的子查询移动到from。我认为这不会对性能产生太大影响。它不相关,所以它运行一次,并返回一个值。

+0

好的,谢谢你指出内连接和左连接,我一直在使用左连接,不必忘记它的目的。所以我认为没有办法让查询进入一个单一的查询。谢谢。我会将此标记为纠正缺陷的答案。 – William

0
SELECT * from catAtt ca 
LEFT JOIN att a ON ca.attId = a.attId 
INNER JOIN 
(
    SELECT DISTINCT eav.catId FROM ent 
    LEFT JOIN eav ON ent.entId = eav.entId 
    WHERE ent.key = 'somekey' 
)Z ON a.attCatId = Z.catId 
WHERE ca.catId = 53 

试试上面的代码。

希望这会帮助你。

+0

这是否会改善性能? – Pasetchnik

+1

你检查了索引吗?索引的存在对连接或子查询的顺序影响更大。数据库引擎通常会对连接和子查询进行重新排序以优化性能,但如果缺少必需的索引,则无法优化任何内容。 –

0

我试过三种查询在sql server上。

SELECT * from catAtt ca JOIN att a ON ca.attId = a.attId 
WHERE ca.catId = 53 AND a.attCatId = 
(
SELECT DISTINCT eav.catId FROM ent LEFT JOIN eav ON ent.entId = eav.entId 
WHERE ent.key = 'somekey' 
) 

SELECT * from catAtt ca 
JOIN att a ON ca.attId = a.attId 
JOIN 
(
    SELECT DISTINCT eav.catId FROM ent 
    LEFT JOIN eav ON ent.entId = eav.entId 
    WHERE ent.key = 'somekey' 
)Z ON a.attCatId = Z.catId 
WHERE ca.catId = 53 

SELECT * from catAtt ca JOIN att a ON ca.attId = a.attId 
WHERE ca.catId = 53 AND 
EXISTS 
    (
    SELECT 1 FROM ent LEFT JOIN eav ON ent.entId = eav.entId 
    WHERE ent.key = 'somekey' AND a.attCatId = eav.catId 
    ) 

而且每个查询的查询成本都是相同的33%。

猜测DataBase比我们聪明。

+0

有趣的是,即使是第三个查询在执行计划中有“独特排序”。 – Pasetchnik