簡體   English   中英

優化此SQL查詢的最佳方法?

[英]Best way to optimize this SQL query?

我正在嘗試獲取每頁5個作業的結果(我將silex與學說結合使用),但是該頁面需要大約30-40秒的加載時間。

  $sql = "
            SELECT jobs.ID, jobs.date_added, jobs.user, jobs.title, jobsmeta.meta_value, jobs_locations_rel.county, jobs_locations_rel.city, usersmeta.meta_value, attachments.title
            FROM jobs
                JOIN jobsmeta
                    ON jobsmeta.parent_id = jobs.ID
                JOIN jobs_locations_rel
                    ON jobs_locations_rel.parent_id = jobs.ID
                JOIN usersmeta
                    ON usersmeta.parent_id = jobs.user
                JOIN attachments
                    ON attachments.ID = (SELECT meta_value FROM usersmeta WHERE parent_id = jobs.ID AND meta_key = 'user_avatar' LIMIT 1)
                ORDER BY jobs.date_added DESC LIMIT 5";
            $data = $app['db']->fetchAll($sql);

這就是解釋計划: 在此處輸入圖片說明 如何優化此查詢以在較短的時間內獲得結果?

通常,如果數據庫設計合理,正確的索引編制就是解決方案。 但是在您的情況下,我在查詢構造中看到了一個(可能的)問題。 由於我不是MySQL專家,因此我認為其他用戶可能會證實我的懷疑。

實際上,您將所有作業與(顯然)“一對多”關系中的其他表結合在一起,這可能會產生更大的結果集ORDER BY只是為了獲取最近添加的前五個記錄。

我認為您應該在WHERE子句中篩選最相關的作業,以減少JOINORDER BY處理。 試試看,包括這段代碼:

WHERE jobs.id IN (SELECT id FROM jobs ORDER BY date_added DESC LIMIT 5)

並檢查您要加入的外鍵列和“ date_added”列是否具有正確的索引。

執行計划顯示僅使用兩個(主鍵)索引。 這應該加以改進。 除了主鍵索引,您還應該嘗試以下附加索引:

  • 職位(用戶)
  • Jobsmeta(parent_id)
  • jobs_locations_rel(parent_id)
  • usersmeta(parent_id,meta_key)

子查詢的LIMIT 1可能也會減慢查詢速度。 這意味着它檢索到的記錄可能是隨機的之一。 這要么意味着您的數據庫設計不便,要么您不希望顯示附件表的所​​有相關記錄。 IN (SELECT ...)不使用LIMIT情況下使用IN (SELECT ...)將確保您擁有所有這些附件記錄。

但是比使用IN更好的方法是將其轉換為附加的JOIN ,如下所示:

SELECT   jobs.ID, jobs.date_added, jobs.user, jobs.title,
         jobsmeta.meta_value,
         jobs_locations_rel.county, jobs_locations_rel.city,
         m1.meta_value, attachments.title
FROM     jobs
JOIN     jobsmeta
      ON jobsmeta.parent_id = jobs.ID
JOIN     jobs_locations_rel
      ON jobs_locations_rel.parent_id = jobs.ID
JOIN     usersmeta m1
      ON m1.parent_id = jobs.user
JOIN     usersmeta m2
      ON m2.parent_id = jobs.ID
     AND m2.meta_key = 'user_avatar'
JOIN     attachments
      ON attachments.ID = m2.meta_value
ORDER BY jobs.date_added DESC
LIMIT 5

另一個奇特的事情: usersmeta.parent_id引用了一個jobs.ID或一個jobs.user值。 這似乎是您可能要查看的數據庫設計中的另一個缺陷。

如果'job.id'值的順序與jobs.date_added的順序相同,則可以考慮執行ORDER BY jobs.id DESC 如果不是,則考慮在jobs(date_added)上創建索引。

最后,您的order by還不夠具體,因為它允許對共享相同jobs.id記錄進行任意排序。 這與性能無關,但是我希望它會使分頁變得困難(取決於您的實現方式)。 最好的辦法是,您可以將ORDER BY子句中列出的列組合在一起,以唯一地標識結果中的記錄。

您可以啟用mysql查詢緩存,以實現更快的重復查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM