[英]MySQL Slow query ~ 10 seconds
我有這個查詢,基本上可以通過一堆表來獲取一些格式化的結果,但是我似乎找不到瓶頸。 最簡單的瓶頸是ORDER BY RAND()
但性能仍然很差。
在沒有ORDER BY RAND()
情況下,查詢耗時10到20秒。
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:
你們做到了。 降低到0.5秒到2.5秒。
我基本上遵循了您的所有建議,並更改了一些在我的表上優化運行的my.cnf +。
您正在以不太理想的方式搜索日期。 嘗試這個。
... 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)
上a (valid_point)
索引。 請注意,您在該表中使用geometry數據類型可能無濟於事。
首先,您有很多索引,但是其中許多沒有用。 請記住,更多的索引意味着較慢的插入和更新。 同樣,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
然后,您有一些重復的數據。
點位
點field
包含lat
和lng
。 因此后兩個不需要。 這意味着您可能會丟失另外兩個索引idxlat
和idxlng
。 我不太確定idxlng如何在同一張表的索引列表中出現兩次。
這些優化將導致INSERTS和UPDATES以及所有SELECT的性能整體提高,因為查詢計划者需要花費更少的時間來決定使用哪個索引。
然后,我們從您的解釋中注意到,該查詢未使用表Adresse
(a)上的任何索引。 但是您的where子句的a.validPoint = 1
顯然需要@ Ollie-Jones建議的索引
但是,我懷疑該索引的基數可能較低。 在這種情況下,我建議您在此列和另一個列上創建一個復合索引。
問題是您加入(a)。 該表具有索引,但是由於排序(/ group by)或可能不兼容的類型,該索引更可能無法使用。 EXPLAIN顯示檢查的一百萬行中的四分之三,這意味着無法進行索引查找。
設計查詢時,請尋找可能的最小結果集-按該索引搜索,然后從那里進行連接。 也許“ c”不是主查詢的最佳表。
(您可以嘗試在表a上使用FORCE INDEX(id),如果它不起作用,則該錯誤可能會為您提供更多信息)。
正如其他人所指出的那樣,你需要一個索引a.validPoint
約但什么c.datePub
那也是在WHERE子句中使用。 為什么不上多列索引datePub, address_id
對指數address_id
已被使用,所以多列索引會更好這里。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.