2014-07-08 209 views
0

我有一個用於返回可用客房的預訂系統如何改善慢速自定義查詢? (子查詢+內有自定義字段合併)

使用Advanced Custom Fields,我代表與各領域

計劃預留的自定義後類型查詢這裏是找到與子查詢所有預訂房間,然後通過選擇不在子查詢返回的結果集中的帖子來獲取所有可用房間

我的預訂自定義帖子有一個「terrain_id」匹配房間的帖子ID(露營或別墅)

第一內加入對房間ID(terrain_id),第二內連接的開始日期,最後一個是在結束日期

所以基本上我的ROOM_ID與POST_ID和收益相匹配所有指定的時間間隔不可用的房間,然後我得到的所有誰在子查詢的結果是不存在的IDS讓我的空房

的問題如下:

這個查詢大約運行小數據樣本5-6秒(約2000個預約,100個房間)

我嘗試不同的方法來優化它,但我幾乎陷入

有所有相關領域

本身在大約0.030秒運行一次,所以我不認爲內連接是子查詢索引問題的大部分似乎是在SELECT不存在

使用默認的wordpress方法和循環不是選項,因爲它是不可能做什麼需要,我需要查詢所有的自定義字段單獨對於每個記錄

我該如何impr我的查詢性能如何?

如何選擇不存在於大約100條記錄數組中的基本屬性可能需要這麼長時間?

SELECT wps.ID, wps.post_title, wps.post_type, wps.post_status 
FROM wp_posts wps, wp_postmeta wpm 
WHERE NOT EXISTS 
(
    SELECT 
     p.ID, 
     pm_ti.meta_value as tiv, 
     pm_ti.meta_key as tik, 
     pm_ed.meta_key as edk, 
     pm_ed.meta_value as edv, 
     pm_sd.meta_key as sdk, 
     pm_sd.meta_value as sdv 
    FROM 
     wp_posts p 
    INNER JOIN wp_postmeta pm_ti ON (pm_ti.post_id = p.ID) 
    INNER JOIN wp_postmeta pm_ed ON (pm_ed.post_id = p.ID) 
    INNER JOIN wp_postmeta pm_sd ON (pm_sd.post_id = p.ID) 
    WHERE NOT (pm_ed.meta_value <= '{$start}' OR pm_sd.meta_value >= '{$end}') 
    AND pm_ti.meta_key='terrain_id' and p.post_status='publish' and wps.ID = pm_ti.meta_value and pm_ed.meta_key='e_date' and pm_sd.meta_key='s_date' 
    GROUP BY p.ID 
) 
AND wpm.post_id = wps.ID AND wps.post_status='publish' AND wps.ID = icl_translations.element_id 
and (wps.post_type='camping' or wps.post_type='cottages') GROUP BY wps.ID 
"); 

解釋結果:

回答

0

我終於設法找到一個像樣的答案

問題的來源是這樣的事實,像這樣的嵌套查詢天生慢,所以我取代了WHERE ...不與負LEFT OUTER JOIN

我開始通過優化內部查詢,因爲它是草率和相同的結果可以以更簡單的方式來實現

然後,用LEFT OUTER替換WHERE條件JOIN以獲得相同的結果

這個問題是非常有益的:

SQL Nested Query slow using IN

原始查詢花費5到15秒之間,

在小於0.05秒

SELECT wps.ID, wps.post_title, pm_ti.meta_value 

FROM wp_posts wps 

LEFT OUTER JOIN 
(

    SELECT 
    pm_ti.meta_value 
    FROM 
    wp_postmeta pm_ti 
    INNER JOIN wp_postmeta pm_ed ON (pm_ed.post_id = pm_ti.post_id) 
    INNER JOIN wp_postmeta pm_sd ON (pm_sd.post_id = pm_ti.post_id) 
    WHERE NOT (pm_ed.meta_value <= '2014-07-01' OR pm_sd.meta_value >= '2014-07-12') 
    AND pm_ti.meta_key='terrain_id' AND pm_ed.meta_key='e_date' AND pm_sd.meta_key='s_date' 

) pm_ti 

ON wps.ID = pm_ti.meta_value 

INNER JOIN wp_icl_translations icl ON (icl.element_id = wps.ID) 

WHERE pm_ti.meta_value IS null AND wps.post_status='publish' 

AND (wps.post_type='camping' OR wps.post_type='cottages') AND icl.language_code = 'fr' 

GROUP BY wps.ID 
2

我不知道你的數據不夠好寫這個100%,但這裏的想法是一樣的。而不是使用相關的子查詢嘗試這樣的事情。

SELECT wps.ID, wps.post_title, wps.post_type, wps.post_status 
FROM wp_posts wps, wp_postmeta wpm 
WHERE wpm.post_id NOT IN 
(
    SELECT 
     DISTINCT pm_ti.meta_value 
    FROM 
     wp_posts p 
    INNER JOIN wp_postmeta pm_ti ON (pm_ti.post_id = p.ID) 
    INNER JOIN wp_postmeta pm_ed ON (pm_ed.post_id = p.ID) 
    INNER JOIN wp_postmeta pm_sd ON (pm_sd.post_id = p.ID) 
    WHERE NOT (pm_ed.meta_value <= '{$start}' OR pm_sd.meta_value >= '{$end}') 
    AND pm_ti.meta_key='terrain_id' 
    AND p.post_status='publish' 
    AND pm_ed.meta_key='e_date' 
    AND pm_sd.meta_key='s_date' 
) 
AND wpm.post_id = wps.ID 
AND wps.post_status='publish' 
AND wps.ID = icl_translations.element_id 
AND (wps.post_type='camping' or wps.post_type='cottages') 

這個想法是返回一個你不想要的ID列表,它不鏈接到主選擇。然後你用NOT IN過濾你的主選擇。

只是要嘗試 - 未經測試。

+0

查詢的修改的查詢的運行方式是更快的,但問題是,代替p.ID,主鍵需要在meta_key「terrain_id」。我試圖讓它工作,我會回報 – user1229829

+0

我更新了這個返回terrain_id值並將其與post_id進行比較,但它確實沒有任何意義,因爲您將id設置爲post_id無論如何。我很困惑你的數據庫。這可能就是我現在想要疲倦的想法。 – Bob

+0

@Bob - 這是標準的WordPress數據庫結構。它基於[TOXI解決方案](http://tagging.pui.ch/post/37027745720/tags-database-schemas)標記結構,因此很混亂。 –