添加和or子句时,MySql Left Join很慢

时间:2014-03-29 13:47:12

标签: mysql performance left-join

我的查询性能有问题。我有以下内容:

SELECT DISTINCT anuncios.id, precios.precio
FROM anuncios
LEFT JOIN precios ON ( (
precios.idcentroanuncio = anuncios.idcentro
AND anuncios.tipoubicacion = 'centropropio'
AND precios.tipocentroanuncio = 'centro'
) )
GROUP BY anuncios.id
LIMIT 0 , 30 

花费0.001 seg。另一方面,我有这个,非常相似:

 SELECT DISTINCT anuncios.id, precios.precio
FROM anuncios
LEFT JOIN precios ON ( 
(
precios.idcentroanuncio = anuncios.id
AND anuncios.tipoubicacion = 'centropropio'
AND precios.tipocentroanuncio = 'centro'
) )
GROUP BY anuncios.id
LIMIT 0 , 30 

也花费相同的时间,或多或少。问题是当我将两个查询合并到这个中时:

 SELECT DISTINCT anuncios.id, precios.precio
FROM anuncios
LEFT JOIN precios ON ( (
precios.idcentroanuncio = anuncios.idcentro
AND anuncios.tipoubicacion = 'centropropio'
AND precios.tipocentroanuncio = 'centro'
)
OR (
precios.idcentroanuncio = anuncios.id
AND anuncios.tipoubicacion = 'centropropio'
AND precios.tipocentroanuncio = 'centro'
) )
GROUP BY anuncios.id
LIMIT 0 , 30 

这里执行时间乘以100.

Theese都是表格解释:

Precios:

+-------------------+------------------+------+-----+---------+----------------+
| Field             | Type             | Null | Key | Default | Extra          |
+-------------------+------------------+------+-----+---------+----------------+
| id                | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| usuario           | varchar(40)      | NO   | MUL | NULL    |                |
| tipocentroanuncio | varchar(50)      | NO   |     | NULL    |                |
| idcentroanuncio   | int(10) unsigned | NO   | MUL | NULL    |                |
| unidades          | float            | NO   |     | NULL    |                |
| tipounidades      | varchar(15)      | NO   |     | NULL    |                |
| precio            | float            | NO   |     | NULL    |                |
| otrosdatosprecio  | varchar(100)     | NO   |     | NULL    |                |
| principal         | int(1) unsigned  | NO   |     | NULL    |                |
+-------------------+------------------+------+-----+---------+----------------+

anuncios:

+------------------+------------------+------+-----+---------------------+----------------+
| Field            | Type             | Null | Key | Default             | Extra          |
+------------------+------------------+------+-----+---------------------+----------------+
| id               | int(10) unsigned | NO   | PRI | NULL                | auto_          |
+------------------+------------------+------+-----+---------------------+------

这是查询的解释:

id  select_type     table   type    possible_keys   key     key_len     ref     rows Extra
1   SIMPLE  anuncios    ALL     NULL    NULL    NULL    NULL    1048578     Using temporary; Using filesort

1   SIMPLE  precios     index   idcentroanuncio     idcentroanuncio     156 NULL    30  Using index

我做错了什么?结合两个独立运行的查询,这次增加是合乎逻辑的吗?

1 个答案:

答案 0 :(得分:1)

是。您已经了解到or可以真正搞乱执行计划。请尝试使用union

SELECT a.id, p.precio
FROM anuncios a LEFT JOIN
     precios p
     ON p.idcentroanuncio = a.idcentro AND
        a.tipoubicacion = 'centropropio' AND 
        p.tipocentroanuncio = 'centro'
UNION
SELECT a.id, p.precio
FROM anuncios a LEFT JOIN
     precios p
     ON p.idcentroanuncio = a.id AND
        a.tipoubicacion = 'centropropio' AND
        p.tipocentroanuncio = 'centro'
LIMIT 0 , 30;

一些笔记,然后是更好的查询。首先,当您distinct时,您不需要group by。其次,此版本不需要group bydistinct,因为union负责使值不同。

为了表现,您可以采取不同的路线。试试这个:

select p.idcentroanuncio, p.price
from precios p
where p.tipocentroanuncio = 'centro' and
      (exists (select 1
               from annuncios a
               where p.idcentroanuncio = a.id and a.tipoubicacion = 'centropropio'
              ) or
       exists (select 1
               from annuncios a
               where p.idcentroanuncio = a.idcentro and a.tipoubicacion = 'centropropio'
              )
      );

这可以消除对distinct的需要。子查询可以各自利用索引:annuncios(id, tipoubicacion)annuncios(idcentro, tipoubicacion)