我有这个查询,基本上通过一堆表来获得一些格式化的结果,但我似乎无法找到瓶颈。最容易的瓶颈是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
以下是解释性查询:
以下是mysqltuner
编辑1
我有很多索引在这里:
编辑2:
所以你们这样做了。低至 .5秒至2.5秒
我主要遵循你的所有建议,并在我的桌子上更改了一些my.cnf + runned优化。
答案 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
中包含lat
和lng
。所以后两者不需要。这意味着您可能会丢失另外两个索引idxlat
和idxlng
。我不太确定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
索引上的多列索引已被使用,因此多列索引在这里会更好。