2016-04-23 158 views
1

我有这个查询基本上经历了一堆表格,让我得到一些格式化的结果,但我似乎无法找到瓶颈。最简单的瓶颈是ORDER BY RAND(),但性能仍然不佳。MySQL缓慢查询〜10秒

查询需要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优化在我的表上。

+0

你是否仅仅通过主表来尝试查询?从只有一张表“immobilier_ad_blank AS c”开始。这将在你的where子句中运用很多部分。然后添加下一个表以完成where子句并查看您的位置。我的直觉是where子句放慢速度的日期格式。 –

+0

请编辑您的问题以显示表格中的索引,也可能是行数。 –

+0

@OllieJones完成。 – delmalki

回答

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)索引。请注意,您在该表中使用几何数据类型可能无助于任何事情。

+0

哇,无语,谁认为复合索引和日期扫描将查询从20秒减少到5秒。赶上!然而,它不一致.. – delmalki

+0

@delmalki尽管STR_TO_DATE位仍然很乏味。只需提交格式正确的日期。 – Strawberry

+0

正确格式化...这是法语格式... – delmalki

0

问题是你加入(a)。该表有一个索引,但索引不能使用,很可能是由于排序(/ group by)或可能不兼容的类型。 EXPLAIN显示检查了四分之三百万行,这意味着索引查找是不可能的。

设计查询时,查找最小可能的结果集 - 按该索引搜索,然后从那里加入。也许“c”不是主要查询的最佳表格。 (你可以尝试在表a上使用FORCE INDEX(id),如果不起作用,错误可能会给你更多的信息)。

2

首先你有很多索引,但其中很多都没有用。记住更多的索引意味着更慢的插入和更新。另外,mysql不擅长在复杂查询中为每个表使用多个索引。以下索引有一个基数< 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 

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

点 纬度 LNG

fieldlat和它lng。所以后两者是不需要的。这意味着你可以丢失两个索引idxlatidxlng。我不太确定idxlng在同一个表的索引列表中如何显示两次。

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

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

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

+0

谢谢你这个彻底的答案。我没有清理我的表格,所以你看到很多重复的东西,我在切换到mysql 5.7之前使用了lat,lng,然后选择了空间索引。另外,我重构了许多表逻辑。 – delmalki

+1

然后你应该清理并运行OPTMIZE,这也是调谐器的建议。 – e4c5

0

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