MySQL慢查询~10秒

时间:2016-04-23 01:27:31

标签: mysql sql

我有这个查询,基本上通过一堆表来获得一些格式化的结果,但我似乎无法找到瓶颈。最容易的瓶颈是ORDER BY RAND(),但性能仍然不好。

查询需要10秒到20秒而不需要ORDER BY RAND();

SELECT 
  c.prix AS prix, 
  ST_X(a.point) AS X, 
  ST_Y(a.point) AS Y, 
  s.sizeFormat AS size, 
  es.name AS estateSize, 
  c.title AS title, 
  DATE_FORMAT(c.datePub, '%m-%d-%y') AS datePub,
  dbr.name AS dateBuiltRange, 
  m.myId AS meuble, 
  c.rawData_id AS rawData_id, 
  GROUP_CONCAT(img.captionWebPath) AS paths 
FROM 
 immobilier_ad_blank AS c 
 LEFT JOIN PropertyFeature AS pf ON (c.propertyFeature_id = pf.id) 
 LEFT JOIN Adresse AS a ON (c.adresse_id = a.id) 
 LEFT JOIN Size AS s ON (pf.size_id = s.id) 
 LEFT JOIN EstateSize AS es ON (pf.estateSize_id = es.id) 
 LEFT JOIN Meuble AS m ON (pf.meuble_id = m.id) 
 LEFT JOIN DateBuiltRange AS dbr ON (pf.dateBuiltRange_id = dbr.id) 
 LEFT JOIN ImageAd AS img ON (img.commonAd_id = c.rawData_id) 
WHERE 
  c.prix != 0
  AND pf.subCatMyId = 1 
  AND (
    (
      c.datePub > STR_TO_DATE('01-04-2016', '%d-%m-%Y') 
      AND c.datePub < STR_TO_DATE('30-04-2016', '%d-%m-%Y')
    ) 
    OR date_format(c.datePub, '%d-%m-%Y') = '30-04-2016'
 ) 
AND a.validPoint = 1 
GROUP BY 
  c.id 
#ORDER BY 
#  RAND() 
LIMIT 
 5000

以下是解释性查询:

enter image description here

视觉部分: enter image description here

以下是mysqltuner

的屏幕截图

enter image description here

编辑1

我有很多索引在这里:

enter image description here enter image description here

编辑2:

所以你们这样做了。低至 .5秒至2.5秒

我主要遵循你的所有建议,并在我的桌子上更改了一些my.cnf + runned优化。

4 个答案:

答案 0 :(得分:2)

您以非常不理想的方式搜索日期。试试这个。

 ...  c.datePub >= STR_TO_DATE('01-04-2016', '%d-%m-%Y') 
  AND c.datePub < STR_TO_DATE('30-04-2016', '%d-%m-%Y') + INTERVAL 1 DAY

允许对datePub列上的索引进行范围扫描。您应该在(datePub, prix, addresse_id, rawData_id)上为该表创建一个复合索引,看看它是否有帮助。

同时尝试a (valid_point)上的索引。请注意,在该表中使用几何数据类型可能没有任何帮助。

答案 1 :(得分:2)

首先,你有很多索引,但其中很多都没用。记住更多索引意味着更慢的插入和更新。此外,mysql不擅长在复杂查询中为每个表使用多个索引。以下索引具有基数&lt; 10,可能应该放弃。

IDX_...E88B
IDX....62AF
IDX....7DEE
idx2
UNIQ...F210
UNIQ...F210..
IDX....0C00
IDX....A2F1
At this point I got tired of the excercise, there are many more

然后你有一些重复的数据。

点    LAT    LNG

field中包含latlng。所以后两者不需要。这意味着您可能会丢失另外两个索引idxlatidxlng。我不太确定idxlng在同一个表的索引列表中出现两次。

这些优化将导致INSERTS和UPDATES的性能整体提升,也可能导致所有SELECT的性能整体提升,因为查询规划器需要花费更少的时间来决定使用哪个索引。

然后我们从您的解释中注意到查询不使用表Adresse(a)上的任何索引。但是你的where子句a.validPoint = 1显然需要@ Ollie-Jones建议的索引

但我怀疑这个指数的基数可能较低。在这种情况下,我建议您在此列+另一个列上创建复合索引。

答案 2 :(得分:0)

问题是您与(a)的联系。该表有一个索引,但索引不能使用,更可能是由于sort(/ group by)或可能不兼容的类型。 EXPLAIN显示检查了四分之三的行,这意味着无法进行索引查找。

设计查询时,查找可能的最小结果集 - 按索引搜索,然后从那里加入。也许“c”不是主要查询的最佳表。

(您可以尝试在表a上使用FORCE INDEX(id),如果它不起作用,该错误可能会为您提供更多信息)。

答案 3 :(得分:0)

正如其他人所指出的那样,你需要a.validPoint上的索引,但是在WHERE子句中也使用了c.datePub。为什么datePub, address_id上的address_id索引上的多列索引已被使用,因此多列索引在这里会更好。