我對MySQL相當陌生,並且一直在研究以下查詢以從wordpress users/usermeta表中提取值列表。查詢工作除了表現是可怕的,我不知道如何改進它。優化/ MySQL查詢
查詢需要12+秒才能完成,只有400個左右的用戶,如果添加更多的話,這將成爲一個巨大的問題。
我注意到MySQL報告沒有唯一的列,但我不知道如何解決這個問題,因爲用戶ID已經是結果的一部分了。
這是默認查詢,完整查詢使用緯度/長度值添加額外計算來確定郵政編碼搜索的距離,但這似乎不會增加太多額外時間。
我掙扎的主要部分是值被保存爲meta_key和meta_value與關聯的user_id作爲外鍵的事實。
SELECT DISTINCT
wp_users.ID,
wp_users.user_email,
city_latitude.meta_value as cityLat,
city_longitude.meta_value as cityLong,
service_name.meta_value as service_name,
service_address.meta_value as service_address,
service_category.meta_value as service_category,
service_level.meta_value as service_level,
service_info.meta_value as service_info,
service_area.meta_value as service_area,
service_active.meta_value as service_active,
service_keyword.meta_value as service_keyword
FROM
wp_usermeta AS city_latitude
LEFT JOIN wp_usermeta as city_longitude ON city_latitude.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_name ON service_name.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_category ON service_category.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_address ON service_address.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_level ON service_level.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_info ON service_info.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_area ON service_area.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_active ON service_active.user_id = city_longitude.user_id
LEFT JOIN wp_usermeta as service_keyword ON service_keyword.user_id = city_longitude.user_id
INNER JOIN wp_users ON wp_users.ID = city_latitude.user_id
WHERE city_latitude.meta_key = 'service_lat'
AND city_longitude.meta_key = 'service_long'
AND (service_name.meta_key = 'service_name' AND service_name.meta_value != 'Anonymous')
AND (service_category.meta_key = 'service_category' ".$query_category.")
AND service_address.meta_key = 'service_address'
AND (service_level.meta_key = 'wp_user_level' AND service_level.meta_value = 0)
AND service_info.meta_key = 'service_additional'
AND service_area.meta_key = 'service_area'
AND service_keyword.meta_key = 'service_keywords'
AND (service_active.meta_key = 'active' AND service_active.meta_value = 1)
ORDER BY service_name ASC
我已經更新了查詢,其中一些建議已經有了很大的改變。我仍然認爲查詢本身可以通過減少連接數量等來改善,如果有人有任何更多的想法我很樂意聽到他們。
這是查詢,其中包括用距離搜索的更改和附加部分。
SELECT DISTINCT
wp_users.ID,
wp_users.user_email,
city_latitude.meta_value as cityLat,
city_longitude.meta_value as cityLong,
service_name.meta_value as service_name,
service_address.meta_value as service_address,
service_category.meta_value as service_category,
service_level.meta_value as service_level,
service_info.meta_value as service_info,
service_area.meta_value as service_area,
service_active.meta_value as service_active,
service_keyword.meta_value as service_keyword,
((ACOS(SIN($userLat * PI()/180) * SIN(city_latitude.meta_value * PI()/180) + COS($userLat * PI()/180) * COS(city_latitude.meta_value * PI()/180) * COS(($userLng - city_longitude.meta_value) * PI()/180)) * 180/PI()) * 60 * 1.1515) AS distance
FROM
wp_usermeta AS usermeta
LEFT JOIN wp_usermeta as city_longitude ON city_longitude.user_id = usermeta.user_id AND city_longitude.meta_key = 'service_long'
LEFT JOIN wp_usermeta as city_latitude ON city_latitude.user_id = usermeta.user_id AND city_latitude.meta_key = 'service_lat'
LEFT JOIN wp_usermeta as service_name ON service_name.user_id = usermeta.user_id AND service_name.meta_key = 'service_name'
LEFT JOIN wp_usermeta as service_category ON service_category.user_id = usermeta.user_id AND service_category.meta_key = 'service_category'
LEFT JOIN wp_usermeta as service_address ON service_address.user_id = usermeta.user_id AND service_address.meta_key = 'service_address'
LEFT JOIN wp_usermeta as service_level ON service_level.user_id = usermeta.user_id AND service_level.meta_key = 'wp_user_level'
LEFT JOIN wp_usermeta as service_info ON service_info.user_id = usermeta.user_id AND service_info.meta_key = 'service_additional'
LEFT JOIN wp_usermeta as service_area ON service_area.user_id = usermeta.user_id AND service_area.meta_key = 'service_area'
LEFT JOIN wp_usermeta as service_active ON service_active.user_id = usermeta.user_id AND service_active.meta_key = 'active'
LEFT JOIN wp_usermeta as service_keyword ON service_keyword.user_id = usermeta.user_id AND service_keyword.meta_key = 'service_keywords'
INNER JOIN wp_users ON wp_users.ID = usermeta.user_id
WHERE (service_name.meta_value != '' AND service_name.meta_value != 'Anonymous') AND service_level.meta_value = 0 AND service_active.meta_value = 1
HAVING distance < $search_distance
ORDER BY distance ASC
刪除這句話是什麼EXPLAIN給?請告訴我們這個。有沒有需要全表掃描的連接?而且您需要將WHERE條件添加到適當的ON部分! – Seb
@P蒼鷺 - 你可以從表格中創建一些樣本日期。沒有必要加入wp_usermeta超過1次。如果您通過http:// sqlfiddle發送一些數據,我會爲您提供查詢。com/ –
@Bernd Buffen - 那真是太好了,謝謝。我已經在[link](http://sqlfiddle.com/#99/af672a)設置了一些數據,我以前從來沒有使用過它,所以它很好。 –