您将如何优化以下mysql查询

时间:2013-07-21 14:45:56

标签: php mysql

任何人都可以帮助我在php中优化这个mysql查询,最多需要100秒。

SELECT DISTINCT
A.X,
A.Y,
A.Z,

FROM TableAA AS A 

INNER JOIN( TableBB AS B) 

ON(A.X = B.X) OR (A.X = B.M)

WHERE B.N = '$input' OR
  A.Y = '$input' OR
  A.Z = '$input'

TableAA拥有100万名企业 TableBB拥有900万名企业

还有其他方法可以编写此查询吗?

编辑:

TableBB在N,X,Y之间的连接上具有PRIMARY索引。 和X,N,M上的索引

TableAA在X上有PRIMARY索引,在Y,Z上有索引

1 个答案:

答案 0 :(得分:0)

您的查询(以我能更好理解的方式格式化)是:

SELECT DISTINCT A.X, A.Y, A.Z
FROM TableAA A INNER JOIN
     TableBB B
     ON A.X = B.X OR A.X = B.M
WHERE B.N = '$input' OR A.Y = '$input' OR A.Z = '$input';

由于所有or子句,这对于优化来说很复杂。我的第一个倾向是使用两个连接而不是or

来编写它
SELECT DISTINCT A.X, A.Y, A.Z
FROM TableAA A left outer JOIN
     TableBB B
     ON A.X = B.X and B.N = '$input' left outer join
     TableBB b2
     on A.X = B2.M and B2.N = '$input'
WHERE (B.N is not null or B2.N is not null) and (A.Y = '$input' OR A.Z = '$input')

这更复杂,但您现在可以在B(N, X)B(N, M)上添加索引以方便处理。

处理or上的A条件也很复杂。您可以尝试使用两个索引:A(Y, X, Z)A(Z, X, Y),看看它们是否被使用。否则,您可以将其拆分为两个查询:

(SELECT A.X, A.Y, A.Z
 FROM TableAA A left outer JOIN
      TableBB B
      ON A.X = B.X and B.N = '$input' left outer join
      TableBB b2
      on A.X = B2.M and B2.N = '$input'
 WHERE (B.N is not null or B2.N is not null) and A.Y = '$input'
)
union
(SELECT A.X, A.Y, A.Z
 FROM TableAA A left outer JOIN
      TableBB B
      ON A.X = B.X and B.N = '$input' left outer join
      TableBB b2
      on A.X = B2.M and B2.N = '$input'
 WHERE (B.N is not null or B2.N is not null) and A.Z = '$input'
)

此版本应使用上述索引。当然,您需要检查explain计划,看看是否真的如此。但这可能有助于优化。

如果有任何方法可以简化条件,使它们and而不是or,那么这种优化就更容易了。