使用多个联接优化sql select

时间:2015-11-23 06:49:21

标签: mysql sql join optimization query-optimization

如何优化此mysql语句?

SELECT DISTINCT p.name
FROM Something_Meta s1
JOIN Something_Meta s2 ON s1.fk_somethingId = s2.fk_somethingId
JOIN Products p ON s2.fk_productId = p.id
JOIN 
(
     select fk_id from Restricted where fk_foo != 233 and fk_id NOT IN 
        (
            Select fk_id  from Restricted where  fk_foo = 233 
        )

)
r ON r.fk_id = p.id
WHERE s1.fk_somethingId = 63 AND s2.fk_somethingId <> s1.fk_somethingId

order by p.name ASC

我的桌子就像那样

Product (id,name ) Restricted (id,fk_id,fk_foo ) Something_Meta (id,fk_id,fk_somethingId )

fk_id是产品的外键(id)

可能是sql语句需要优化..

 select fk_id from Restricted where fk_foo != 233 and fk_id NOT IN 
    (
        Select fk_id  from Restricted where  fk_foo = 233 
    )

整个查询语句的运行时间超过1.5秒,单个查询的网站需要多秒。

2 个答案:

答案 0 :(得分:0)

您可以尝试(fk_foo, fk_id)上的索引来覆盖整个查询:

create index ix_restricted_fk_foo_fk_id(fk_foo, fk_id) on restricted

答案 1 :(得分:0)

首先关闭:DISTINCT有点红旗。如果您需要过滤掉双打,那么可能会出现错误(在查询或设计中)导致双打。

二;你可以写这样的查询:

SELECT DISTINCT p.name
FROM Something_Meta s1
JOIN Something_Meta s2 ON s1.fk_somethingId = s2.fk_somethingId
JOIN Products p ON s2.fk_productId = p.id

WHERE s1.fk_somethingId = 63 AND s2.fk_somethingId <> s1.fk_somethingId
AND NOT EXISTS ( SELECT *
                   FROM Restricted r
                  WHERE r.fk_foo != 233 
                    AND r.fk_id  = p.id )
AND EXISTS ( SELECT *
               FROM Restricted r2
              WHERE r2.fk_foo = 233
                AND r2.fk_id = p.id )

order by p.name ASC

由于我对Something_Meta表没有任何线索,我只关注Restricted表并建议你在fk_foo和fk_id上放一个索引。所述索引不是查询的一部分,而是表的一部分,因此您必须预先定义一次。

CREATE INDEX idx_Restricted ON Restricted (fk_id, fk_foo)

一旦指数存在;任何可能从中受益的查询都会在后台自动使用它;你不需要为它调整查询。

侧面说明;因为你显然在寻找产品我觉得很奇怪你没有把注意力集中在Products上。

SELECT p.name
  FROM Products p
  JOIN etc...