2014-03-29 81 views
1

我有一個查詢的性能問題時。我有以下內容:MySQL的左連接緩慢增加和或條款

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 

也花費的同時,更多或更少。問題是,當我的兩個查詢合併成這一個:100。

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 

這裏的執行時間乘以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 

我在做什麼錯?這次合併兩個獨立快速運行的查詢是否合乎邏輯?

+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; 

有些筆記,然後更好的查詢。首先,當你有group by時,你不需要distinct。其次,這個版本並不需要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)

+0

遺憾,當時的想法是也顯示價格。我已將原始查詢減少到最大值以查找問題。我更新查詢。我會嘗試你的建議與聯盟條款。 – oskar

+0

@oskar。 。 。你可以在第一個查詢中添加'price'來獲得你想要的。 –

+0

第一點似乎正常工作,只是適應一對事物。這似乎是正確的查詢: SELECT anuncios.id,precios.precio FROM anuncios LEFT JOIN precios ON(( precios.idcentroanuncio = anuncios.idcentro AND anuncios.tipoubicacion = 'centropropio' 和precios.tipocentroanuncio = '炫酷' )) GROUP BY anuncios.id LIMIT 0,30 UNION SELECT anuncios.id,precios.precio FROM anuncios LEFT JOIN precios ON(( precios.idcentroanuncio = anuncios。ID AND anuncios.tipoubicacion = 'centropropio' AND precios.tipocentroanuncio = '炫酷' )) GROUP BY anuncios.id LIMIT 0,30 – oskar