0

任何人都可以帮助我在 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 上有索引

4

1 回答 1

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条件 onA也很复杂。您可以尝试使用两个索引: 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,那么这种优化更容易。

于 2013-07-21T14:57:18.220 回答